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(FlashScopeManagerConfiguration.class.getName()); 79 if (cfg != null) 80 { 81 manager = new AccessScopeManager(); 82 manager.setAccessScopeManagerConfiguration(cfg); 83 fa.setRequestAttribute(REQ_ATTR_KEY, manager); 84 return manager; 85 } 86 87 // normal case 88 manager = (AccessScopeManager) fa.getBean(AccessScopeManager.class.getName()); 89 if (manager != null) 90 { 91 fa.setRequestAttribute(REQ_ATTR_KEY, manager); 92 return manager; 93 } 94 95 // TODO: Make this error message less spring-specific. Spring is not the only IOC container 96 // that Orchestra can be used with. 97 throw new IllegalArgumentException( 98 "No AccessScopeManager found. Probably you forgot to add " 99 + "<import resource=\"classpath*:/META-INF/spring-orchestra-init.xml\" />" 100 + " to your spring configuration."); 101 } 102 103 public AccessScopeManagerConfiguration getAccessScopeManagerConfiguration() 104 { 105 return accessScopeManagerConfiguration; 106 } 107 108 public void setAccessScopeManagerConfiguration(AccessScopeManagerConfiguration accessScopeManagerConfiguration) 109 { 110 this.accessScopeManagerConfiguration = accessScopeManagerConfiguration; 111 } 112 113 /** 114 * This is invoked at the point in the request lifecycle after which we want to 115 * start tracking use of access-scoped objects. 116 */ 117 public void beginRecording() 118 { 119 recordAccess = true; 120 } 121 122 /** 123 * Add a conversation to the list of accessed conversations. 124 * <p> 125 * This method is expected to be called via AOP proxies wrapped around each conversation-scoped 126 * bean; any invocation of a method on such a bean causes the conversation associated with that 127 * bean to be added to the accessed list here. 128 */ 129 public void addConversationAccess(String conversationName) 130 { 131 // Don't bother tracking accessed conversations if we will never use the data. 132 // Otherwise, add this conversation name to the list of accessed conversations. 133 if (recordAccess && !ignoreRequest && !accessedConversations.contains(conversationName)) 134 { 135 accessedConversations.add(conversationName); 136 } 137 } 138 139 public boolean isIgnoreRequest() 140 { 141 return ignoreRequest; 142 } 143 144 /** 145 * Suppress access scope for the current request, ie do not terminate conversations that are 146 * not accessed by this request. 147 * <p> 148 * This can come in useful occasionally, particularly when handling AJAX requests which 149 * only access some of the beans associated with the current view. 150 */ 151 public void setIgnoreRequest() 152 { 153 this.ignoreRequest = true; 154 } 155 156 public boolean isConversationAccessed(String name) 157 { 158 if (ignoreRequest) 159 { 160 throw new IllegalStateException(); 161 } 162 163 return accessedConversations.contains(name); 164 } 165 }