1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 package org.apache.myfaces.orchestra.conversation; 20 21 import java.util.HashSet; 22 import java.util.Set; 23 24 import org.apache.myfaces.orchestra.frameworkAdapter.FrameworkAdapter; 25 26 /** 27 * Manager to deal with page scoped beans. 28 * <p> 29 * Instances of this type are expected to be request-scoped, ie a new instance is used for 30 * each request. The AccessScopeManagerConfiguration object that it references can be 31 * of application scope. 32 * 33 * @since 1.1 34 */ 35 public class AccessScopeManager 36 { 37 private static final String REQ_ATTR_KEY = AccessScopeManager.class.getName(); 38 private AccessScopeManagerConfiguration accessScopeManagerConfiguration; 39 40 private boolean recordAccess; 41 private boolean ignoreRequest; 42 private Set accessedConversations = new HashSet(); 43 44 public static AccessScopeManager getInstance() 45 { 46 // Get the instance by looking up a variable whose name is this class name, using the normal 47 // managed bean lookup process. When an IOC framework like Spring is being used to extend 48 // the standard JSF managed bean declaration facilities, then the bean may be retrieved 49 // from there. 50 // 51 // Using a lookup of a managed bean allows the user to set configuration properties on the 52 // manager class and its properties. 53 54 FrameworkAdapter fa = FrameworkAdapter.getCurrentInstance(); 55 AccessScopeManager manager = (AccessScopeManager) fa.getRequestAttribute(REQ_ATTR_KEY); 56 if (manager != null) 57 { 58 // already found and cached in request attributes 59 return manager; 60 } 61 62 // Backwards compatibility hack: look for FlashScopeManager. It is possible that 63 // a user of Orchestra 1.0 has copied the declaration from the original Orchestra 64 // config file into their own code to inject special settings. 65 manager = (AccessScopeManager) fa.getBean(FlashScopeManager.class.getName()); 66 if (manager != null) 67 { 68 fa.setRequestAttribute(REQ_ATTR_KEY, manager); 69 return manager; 70 } 71 72 // Backwards compatibility hack: look for FlashScopeManagerConfiguration. It is 73 // possible that a user of Orchestra 1.0 has overridden just the Configuration 74 // bit to set their own ignoredViewId values (as recommended!): 75 // 76 // This is a little dodgy as settings made through the new AccessScopeManage 77 // bean will will now be silently ignored. 78 FlashScopeManagerConfiguration cfg = (FlashScopeManagerConfiguration) fa.getBean( 79 FlashScopeManagerConfiguration.class.getName()); 80 if (cfg != null) 81 { 82 manager = new AccessScopeManager(); 83 manager.setAccessScopeManagerConfiguration(cfg); 84 fa.setRequestAttribute(REQ_ATTR_KEY, manager); 85 return manager; 86 } 87 88 // normal case 89 manager = (AccessScopeManager) fa.getBean(AccessScopeManager.class.getName()); 90 if (manager != null) 91 { 92 fa.setRequestAttribute(REQ_ATTR_KEY, manager); 93 return manager; 94 } 95 96 // TODO: Make this error message less spring-specific. Spring is not the only IOC container 97 // that Orchestra can be used with. 98 throw new IllegalArgumentException( 99 "No AccessScopeManager found. Probably you forgot to add " 100 + "<import resource=\"classpath*:/META-INF/spring-orchestra-init.xml\" />" 101 + " to your spring configuration."); 102 } 103 104 public AccessScopeManagerConfiguration getAccessScopeManagerConfiguration() 105 { 106 return accessScopeManagerConfiguration; 107 } 108 109 public void setAccessScopeManagerConfiguration(AccessScopeManagerConfiguration accessScopeManagerConfiguration) 110 { 111 this.accessScopeManagerConfiguration = accessScopeManagerConfiguration; 112 } 113 114 /** 115 * This is invoked at the point in the request lifecycle after which we want to 116 * start tracking use of access-scoped objects. 117 */ 118 public void beginRecording() 119 { 120 recordAccess = true; 121 } 122 123 /** 124 * Add a conversation to the list of accessed conversations. 125 * <p> 126 * This method is expected to be called via AOP proxies wrapped around each conversation-scoped 127 * bean; any invocation of a method on such a bean causes the conversation associated with that 128 * bean to be added to the accessed list here. 129 */ 130 public void addConversationAccess(String conversationName) 131 { 132 // Don't bother tracking accessed conversations if we will never use the data. 133 // Otherwise, add this conversation name to the list of accessed conversations. 134 if (recordAccess && !ignoreRequest && !accessedConversations.contains(conversationName)) 135 { 136 accessedConversations.add(conversationName); 137 } 138 } 139 140 public boolean isIgnoreRequest() 141 { 142 return ignoreRequest; 143 } 144 145 /** 146 * Suppress access scope for the current request, ie do not terminate conversations that are 147 * not accessed by this request. 148 * <p> 149 * This can come in useful occasionally, particularly when handling AJAX requests which 150 * only access some of the beans associated with the current view. 151 */ 152 public void setIgnoreRequest() 153 { 154 this.ignoreRequest = true; 155 } 156 157 public boolean isConversationAccessed(String name) 158 { 159 if (ignoreRequest) 160 { 161 throw new IllegalStateException(); 162 } 163 164 return accessedConversations.contains(name); 165 } 166 }