Modified: turbine/core/trunk/src/java/org/apache/turbine/services/schedule/WorkerThread.java URL: http://svn.apache.org/viewvc/turbine/core/trunk/src/java/org/apache/turbine/services/schedule/WorkerThread.java?rev=1812628&r1=1812627&r2=1812628&view=diff ============================================================================== --- turbine/core/trunk/src/java/org/apache/turbine/services/schedule/WorkerThread.java (original) +++ turbine/core/trunk/src/java/org/apache/turbine/services/schedule/WorkerThread.java Thu Oct 19 12:34:25 2017 @@ -1,101 +1,101 @@ -package org.apache.turbine.services.schedule; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.turbine.modules.ScheduledJobLoader; - -/** - * Wrapper for a <code>JobEntry</code> to actually perform the job's action. - * - * @author <a href="mailto:[email protected]">Dave Bryson</a> - * @author <a href="mailto:[email protected]">Daniel Rall</a> - * @author <a href="mailto:[email protected]">Henning P. Schmiedehausen</a> - * @author <a href="mailto:[email protected]">Quinton McCombs</a> - * @version $Id: WorkerThread.java 534527 2007-05-02 16:10:59Z tv $ - */ -public class WorkerThread - implements Runnable -{ - /** - * The <code>JobEntry</code> to run. - */ - private JobEntry je = null; - - /** Logging */ - private static Log log = LogFactory.getLog(ScheduleService.LOGGER_NAME); - - /** - * Creates a new worker to run the specified <code>JobEntry</code>. - * - * @param je The <code>JobEntry</code> to create a worker for. - */ - public WorkerThread(JobEntry je) - { - this.je = je; - } - - /** - * Run the job. - */ - @Override - public void run() - { - if (je == null || je.isActive()) - { - return; - } - - try - { - if (!je.isActive()) - { - je.setActive(true); - logStateChange("started"); - ScheduledJobLoader.getInstance().exec(je, je.getTask()); - } - } - catch (Exception e) - { - log.error("Error in WorkerThread for scheduled job #" + - je.getJobId() + ", task: " + je.getTask(), e); - } - finally - { - if (je.isActive()) - { - je.setActive(false); - logStateChange("completed"); - } - } - } - - /** - * Macro to log <code>JobEntry</code> status information. - * - * @param state The new state of the <code>JobEntry</code>. - */ - private final void logStateChange(String state) - { - log.debug("Scheduled job #" + je.getJobId() + ' ' + state + - ", task: " + je.getTask()); - } -} +package org.apache.turbine.services.schedule; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.turbine.modules.ScheduledJobLoader; + +/** + * Wrapper for a <code>JobEntry</code> to actually perform the job's action. + * + * @author <a href="mailto:[email protected]">Dave Bryson</a> + * @author <a href="mailto:[email protected]">Daniel Rall</a> + * @author <a href="mailto:[email protected]">Henning P. Schmiedehausen</a> + * @author <a href="mailto:[email protected]">Quinton McCombs</a> + * @version $Id: WorkerThread.java 534527 2007-05-02 16:10:59Z tv $ + */ +public class WorkerThread + implements Runnable +{ + /** + * The <code>JobEntry</code> to run. + */ + private JobEntry je = null; + + /** Logging */ + private static Log log = LogFactory.getLog(ScheduleService.LOGGER_NAME); + + /** + * Creates a new worker to run the specified <code>JobEntry</code>. + * + * @param je The <code>JobEntry</code> to create a worker for. + */ + public WorkerThread(JobEntry je) + { + this.je = je; + } + + /** + * Run the job. + */ + @Override + public void run() + { + if (je == null || je.isActive()) + { + return; + } + + try + { + if (!je.isActive()) + { + je.setActive(true); + logStateChange("started"); + ScheduledJobLoader.getInstance().exec(je, je.getTask()); + } + } + catch (Exception e) + { + log.error("Error in WorkerThread for scheduled job #" + + je.getJobId() + ", task: " + je.getTask(), e); + } + finally + { + if (je.isActive()) + { + je.setActive(false); + logStateChange("completed"); + } + } + } + + /** + * Macro to log <code>JobEntry</code> status information. + * + * @param state The new state of the <code>JobEntry</code>. + */ + private final void logStateChange(String state) + { + log.debug("Scheduled job #" + je.getJobId() + ' ' + state + + ", task: " + je.getTask()); + } +}
Modified: turbine/core/trunk/src/java/org/apache/turbine/services/security/DefaultSecurityService.java URL: http://svn.apache.org/viewvc/turbine/core/trunk/src/java/org/apache/turbine/services/security/DefaultSecurityService.java?rev=1812628&r1=1812627&r2=1812628&view=diff ============================================================================== --- turbine/core/trunk/src/java/org/apache/turbine/services/security/DefaultSecurityService.java (original) +++ turbine/core/trunk/src/java/org/apache/turbine/services/security/DefaultSecurityService.java Thu Oct 19 12:34:25 2017 @@ -125,7 +125,7 @@ public class DefaultSecurityService { this.userManager = (UserManager) Class.forName(userManagerClassName).newInstance(); - + userManager.init(conf); } catch (Exception e) Modified: turbine/core/trunk/src/java/org/apache/turbine/services/security/DefaultUserManager.java URL: http://svn.apache.org/viewvc/turbine/core/trunk/src/java/org/apache/turbine/services/security/DefaultUserManager.java?rev=1812628&r1=1812627&r2=1812628&view=diff ============================================================================== --- turbine/core/trunk/src/java/org/apache/turbine/services/security/DefaultUserManager.java (original) +++ turbine/core/trunk/src/java/org/apache/turbine/services/security/DefaultUserManager.java Thu Oct 19 12:34:25 2017 @@ -1,516 +1,516 @@ -package org.apache.turbine.services.security; - - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fulcrum.factory.FactoryService; -import org.apache.fulcrum.security.acl.AccessControlList; -import org.apache.fulcrum.security.model.turbine.TurbineUserManager; -import org.apache.fulcrum.security.model.turbine.entity.TurbineUser; -import org.apache.fulcrum.security.util.DataBackendException; -import org.apache.fulcrum.security.util.EntityExistsException; -import org.apache.fulcrum.security.util.PasswordMismatchException; -import org.apache.fulcrum.security.util.UnknownEntityException; -import org.apache.fulcrum.security.util.UserSet; -import org.apache.turbine.om.security.TurbineUserDelegate; -import org.apache.turbine.om.security.User; -import org.apache.turbine.services.InitializationException; -import org.apache.turbine.services.ServiceManager; -import org.apache.turbine.services.TurbineServices; -import org.apache.turbine.util.ObjectUtils; - -/** - * Default user manager. - * - * The user manager wraps Fulcrum security user objects into - * Turbine-specific ones. - * - * - * <ol><li>either in a method with the same name (and very similar signature) - * <li>or mapped to method names as listed below: - * - * <ul> - * <li>method(s) in this manager -> Fulcrum manager method(s) - * <li>{@link #createAccount(User, String)}createAccount -> addUser(User, String) - * <li> {@link #removeAccount(User)} -> removeUser(User) - * <li>{@link #store(User)} -> saveUser(User) - * <li>{@link #retrieve(String)} and {@link #retrieve(String, String)} -> getUser(String), getUser(String, String) - * <li>{@link #retrieveList(Object)} ->getAllUsers() - * <li>{@link #accountExists(String)}, {@link #accountExists(User)} -> checkExists(String), checkExists(User) - * - * In this way all public methods of Fulcrum {@link TurbineUserManager} interface are used by reference of the Fulcrum delegate {@link #umDelegate} - * and wrapped by this manager. - * - * @author <a href="mailto:[email protected]">Thomas Vandahl</a> - * @version $Id: PassiveUserManager.java 1096130 2011-04-23 10:37:19Z ludwig $ - */ -public class DefaultUserManager implements UserManager -{ - /** Fulcrum user manager instance to delegate to */ - private TurbineUserManager umDelegate = null; - - private FactoryService factoryService = null; - - /** The user class, which the UserManager uses as wrapper for Fulcrum {@link TurbineUser} */ - private String userWrapperClass; - - - /** Logging */ - private static Log log = LogFactory.getLog(DefaultUserManager.class); - - /** - * Wrap a Fulcrum user object into a Turbine user object - * - * @param user the user object to delegate to - * - * @return the wrapped object - */ - protected <U extends User> U wrap(TurbineUser user) - { - // U u = (U)new DefaultUserImpl(user); - @SuppressWarnings("unchecked") - U u = (U) getUserWrapper(user); - return u; - } - - /** - * Exception could be ignored, as it is tested before in {@link #init(Configuration)}. - * - * @param user the user object to wrap - * @return instance extending {@link User} - */ - @SuppressWarnings("unchecked") - public <U extends User> U getUserWrapper(TurbineUser user) - { - try - { - Object params[] = new Object[] { user }; - String signature[] = new String[] { TurbineUser.class.getName() }; - return (U) factoryService.getInstance(getUserWrapperClass(), params, signature); - } - catch (Exception e) - { - log.error("after init/late instantiation exception", e); - return null; // (U)new DefaultUserImpl(user); - } - } - - /** - * Get the wrapper class for user objects - * - * @return the wrapper class name - */ - public String getUserWrapperClass() - { - return userWrapperClass; - } - - /** - * Set the wrapper class for user objects - * - * @param userWrapperClass2 the wrapper class name - */ - public void setUserWrapperClass(String userWrapperClass2) - { - userWrapperClass = userWrapperClass2; - } - - /** - * Initializes the UserManager - * - * @param conf A Configuration object to init this Manager - */ - @Override - public void init(Configuration conf) throws InitializationException - { - ServiceManager manager = TurbineServices.getInstance(); - this.umDelegate = (TurbineUserManager)manager.getService(TurbineUserManager.ROLE); - - String userWrapperClass = conf.getString( - SecurityService.USER_WRAPPER_KEY, - SecurityService.USER_WRAPPER_DEFAULT); - -// String userClass = conf.getString( -// SecurityService.USER_KEY, -// SecurityService.USER_DEFAULT); - - try - { - factoryService = (FactoryService)manager.getService(FactoryService.ROLE); - - // check instantiation - - // should provide default constructor - TurbineUser turbineUser = umDelegate.getUserInstance(); - //(TurbineUser) factoryService.getInstance(userClass); - Object params[] = new Object[] { turbineUser }; - String signature[] = new String[] { TurbineUser.class.getName() }; - - // Just check if exceptions would occur - factoryService.getInstance(userWrapperClass, params, signature); - - this.setUserWrapperClass(userWrapperClass); - } - catch (Exception e) - { - throw new InitializationException("Failed to instantiate user wrapper class", e); - } - - } - - - /** - * Check whether a specified user's account exists. - * - * The login name is used for looking up the account. - * - * @param user The user to be checked. - * @return true if the specified account exists - * @throws DataBackendException if there was an error accessing the data backend. - */ - @Override - public boolean accountExists(User user) - throws DataBackendException - { - return umDelegate.checkExists(user); - } - - /** - * Check whether a specified user's account exists. - * - * The login name is used for looking up the account. - * - * @param userName The name of the user to be checked. - * @return true if the specified account exists - * @throws DataBackendException if there was an error accessing the data backend. - */ - @Override - public boolean accountExists(String userName) - throws DataBackendException - { - return umDelegate.checkExists(userName); - } - - /** - * Retrieve a user from persistent storage using username as the - * key. - * - * @param username the name of the user. - * @return an User object. - * @throws UnknownEntityException if the user's record does not - * exist in the database. - * @throws DataBackendException if there is a problem accessing the - * storage. - */ - @Override - public <U extends User> U retrieve(String username) - throws UnknownEntityException, DataBackendException - { - TurbineUser u = umDelegate.getUser(username); - return wrap(u); - } - - /** - * Retrieve a set of users that meet the specified criteria. - * - * As the keys for the criteria, you should use the constants that - * are defined in {@link User} interface, plus the names - * of the custom attributes you added to your user representation - * in the data storage. Use verbatim names of the attributes - - * without table name prefix in case of DB implementation. - * - * @param criteria The criteria of selection. - * @return a List of users meeting the criteria. - * @throws DataBackendException if there is a problem accessing the - * storage. - */ - @Override - public List<? extends User> retrieveList(Object criteria) - throws DataBackendException - { - UserSet uset = umDelegate.getAllUsers(); - List<User> userList = new ArrayList<User>(); - - for (org.apache.fulcrum.security.entity.User u : uset) - { - TurbineUser tu = (TurbineUser)u; - userList.add(wrap(tu)); - } - - return userList; - } - - /** - * Retrieve a user from persistent storage using username as the - * key, and authenticate the user. The implementation may chose - * to authenticate to the server as the user whose data is being - * retrieved. - * - * @param username the name of the user. - * @param password the user supplied password. - * @return an User object. - * @throws PasswordMismatchException if the supplied password was - * incorrect. - * @throws UnknownEntityException if the user's record does not - * exist in the database. - * @throws DataBackendException if there is a problem accessing the - * storage. - */ - @Override - public <U extends User> U retrieve(String username, String password) - throws PasswordMismatchException, UnknownEntityException, - DataBackendException - { - TurbineUser u = umDelegate.getUser(username, password); - return wrap(u); - } - - /** - * Save an User object to persistent storage. User's record is - * required to exist in the storage. - * - * @param user an User object to store. - * @throws UnknownEntityException if the user's record does not - * exist in the database. - * @throws DataBackendException if there is a problem accessing the - * storage. - */ - @Override - public void store(User user) - throws UnknownEntityException, DataBackendException - { - try - { - user.setObjectdata(ObjectUtils.serializeMap(user.getPermStorage())); - } - catch (Exception e) - { - throw new DataBackendException("Could not serialize permanent storage", e); - } - - umDelegate.saveUser(((TurbineUserDelegate)user).getUserDelegate()); - } - - /** - * Saves User data when the session is unbound. The user account is required - * to exist in the storage. - * - * LastLogin, AccessCounter, persistent pull tools, and any data stored - * in the permData hashtable that is not mapped to a column will be saved. - * - * @throws UnknownEntityException if the user's account does not - * exist in the database. - * @throws DataBackendException if there is a problem accessing the - * storage. - */ - @Override - public void saveOnSessionUnbind(User user) - throws UnknownEntityException, DataBackendException - { - store(user); - } - - /** - * Authenticate an User with the specified password. If authentication - * is successful the method returns nothing. If there are any problems, - * exception was thrown. - * - * @param user an User object to authenticate. - * @param password the user supplied password. - * @throws PasswordMismatchException if the supplied password was - * incorrect. - * @throws UnknownEntityException if the user's record does not - * exist in the database. - * @throws DataBackendException if there is a problem accessing the - * storage. - */ - @Override - public void authenticate(User user, String password) - throws PasswordMismatchException, UnknownEntityException, - DataBackendException - { - umDelegate.authenticate(user, password); - } - - /** - * Creates new user account with specified attributes. - * - * @param user the object describing account to be created. - * @param initialPassword The password to use for the object creation - * - * @throws DataBackendException if there was an error accessing the data backend. - * @throws EntityExistsException if the user account already exists. - */ - @Override - public void createAccount(User user, String initialPassword) - throws EntityExistsException, DataBackendException - { - umDelegate.addUser(user, initialPassword); - } - - /** - * Removes an user account from the system. - * - * @param user the object describing the account to be removed. - * @throws DataBackendException if there was an error accessing the data backend. - * @throws UnknownEntityException if the user account is not present. - */ - @Override - public void removeAccount(User user) - throws UnknownEntityException, DataBackendException - { - umDelegate.removeUser(user); - } - - /** - * Change the password for an User. - * - * @param user an User to change password for. - * @param oldPassword the current password supplied by the user. - * @param newPassword the current password requested by the user. - * @throws PasswordMismatchException if the supplied password was - * incorrect. - * @throws UnknownEntityException if the user's record does not - * exist in the database. - * @throws DataBackendException if there is a problem accessing the - * storage. - */ - @Override - public void changePassword(User user, String oldPassword, - String newPassword) - throws PasswordMismatchException, UnknownEntityException, - DataBackendException - { - umDelegate.changePassword( - ((TurbineUserDelegate)user).getUserDelegate(), - oldPassword, newPassword); - } - - /** - * Forcibly sets new password for an User. - * - * This is supposed by the administrator to change the forgotten or - * compromised passwords. Certain implementations of this feature - * would require administrative level access to the authenticating - * server / program. - * - * @param user an User to change password for. - * @param password the new password. - * @throws UnknownEntityException if the user's record does not - * exist in the database. - * @throws DataBackendException if there is a problem accessing the - * storage. - */ - @Override - public void forcePassword(User user, String password) - throws UnknownEntityException, DataBackendException - { - umDelegate.forcePassword(user, password); - } - - /** - * Constructs an User object to represent an anonymous user of the - * application. - * - * @return An anonymous Turbine User. - * @throws UnknownEntityException - * if the anonymous User object couldn't be constructed. - */ - @Override - public <T extends User> T getAnonymousUser() throws UnknownEntityException - { - TurbineUser u = umDelegate.getAnonymousUser(); - return wrap(u); - } - - /** - * Checks whether a passed user object matches the anonymous user pattern - * according to the configured user manager - * - * @param u a user object - * - * @return True if this is an anonymous user - * - */ - @Override - public boolean isAnonymousUser(User u) - { - return umDelegate.isAnonymousUser(u); - } - - /** - * Construct a blank User object. - * - * This method calls getUserClass, and then creates a new object using the - * default constructor. - * - * @return an object implementing User interface. - * @throws DataBackendException - * if the object could not be instantiated. - */ - @Override - public <T extends User> T getUserInstance() throws DataBackendException - { - TurbineUser u = umDelegate.getUserInstance(); - return wrap(u); - } - - /** - * Construct a blank User object. - * - * This method calls getUserClass, and then creates a new object using the - * default constructor. - * - * @param userName - * The name of the user. - * - * @return an object implementing User interface. - * @throws DataBackendException - * if the object could not be instantiated. - */ - @Override - public <T extends User> T getUserInstance(String userName) throws DataBackendException - { - TurbineUser u = umDelegate.getUserInstance(userName); - return wrap(u); - } - - /** - * Return a Class object representing the system's chosen implementation of - * of ACL interface. - * - * @return systems's chosen implementation of ACL interface. - * @throws UnknownEntityException - * if the implementation of ACL interface could not be - * determined, or does not exist. - */ - @Override - public <T extends AccessControlList> T getACL(User user) throws UnknownEntityException - { - return umDelegate.getACL(user); - } -} +package org.apache.turbine.services.security; + + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.configuration.Configuration; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fulcrum.factory.FactoryService; +import org.apache.fulcrum.security.acl.AccessControlList; +import org.apache.fulcrum.security.model.turbine.TurbineUserManager; +import org.apache.fulcrum.security.model.turbine.entity.TurbineUser; +import org.apache.fulcrum.security.util.DataBackendException; +import org.apache.fulcrum.security.util.EntityExistsException; +import org.apache.fulcrum.security.util.PasswordMismatchException; +import org.apache.fulcrum.security.util.UnknownEntityException; +import org.apache.fulcrum.security.util.UserSet; +import org.apache.turbine.om.security.TurbineUserDelegate; +import org.apache.turbine.om.security.User; +import org.apache.turbine.services.InitializationException; +import org.apache.turbine.services.ServiceManager; +import org.apache.turbine.services.TurbineServices; +import org.apache.turbine.util.ObjectUtils; + +/** + * Default user manager. + * + * The user manager wraps Fulcrum security user objects into + * Turbine-specific ones. + * + * + * <ol><li>either in a method with the same name (and very similar signature) + * <li>or mapped to method names as listed below: + * + * <ul> + * <li>method(s) in this manager -> Fulcrum manager method(s) + * <li>{@link #createAccount(User, String)}createAccount -> addUser(User, String) + * <li> {@link #removeAccount(User)} -> removeUser(User) + * <li>{@link #store(User)} -> saveUser(User) + * <li>{@link #retrieve(String)} and {@link #retrieve(String, String)} -> getUser(String), getUser(String, String) + * <li>{@link #retrieveList(Object)} ->getAllUsers() + * <li>{@link #accountExists(String)}, {@link #accountExists(User)} -> checkExists(String), checkExists(User) + * + * In this way all public methods of Fulcrum {@link TurbineUserManager} interface are used by reference of the Fulcrum delegate {@link #umDelegate} + * and wrapped by this manager. + * + * @author <a href="mailto:[email protected]">Thomas Vandahl</a> + * @version $Id: PassiveUserManager.java 1096130 2011-04-23 10:37:19Z ludwig $ + */ +public class DefaultUserManager implements UserManager +{ + /** Fulcrum user manager instance to delegate to */ + private TurbineUserManager umDelegate = null; + + private FactoryService factoryService = null; + + /** The user class, which the UserManager uses as wrapper for Fulcrum {@link TurbineUser} */ + private String userWrapperClass; + + + /** Logging */ + private static Log log = LogFactory.getLog(DefaultUserManager.class); + + /** + * Wrap a Fulcrum user object into a Turbine user object + * + * @param user the user object to delegate to + * + * @return the wrapped object + */ + protected <U extends User> U wrap(TurbineUser user) + { + // U u = (U)new DefaultUserImpl(user); + @SuppressWarnings("unchecked") + U u = (U) getUserWrapper(user); + return u; + } + + /** + * Exception could be ignored, as it is tested before in {@link #init(Configuration)}. + * + * @param user the user object to wrap + * @return instance extending {@link User} + */ + @SuppressWarnings("unchecked") + public <U extends User> U getUserWrapper(TurbineUser user) + { + try + { + Object params[] = new Object[] { user }; + String signature[] = new String[] { TurbineUser.class.getName() }; + return (U) factoryService.getInstance(getUserWrapperClass(), params, signature); + } + catch (Exception e) + { + log.error("after init/late instantiation exception", e); + return null; // (U)new DefaultUserImpl(user); + } + } + + /** + * Get the wrapper class for user objects + * + * @return the wrapper class name + */ + public String getUserWrapperClass() + { + return userWrapperClass; + } + + /** + * Set the wrapper class for user objects + * + * @param userWrapperClass2 the wrapper class name + */ + public void setUserWrapperClass(String userWrapperClass2) + { + userWrapperClass = userWrapperClass2; + } + + /** + * Initializes the UserManager + * + * @param conf A Configuration object to init this Manager + */ + @Override + public void init(Configuration conf) throws InitializationException + { + ServiceManager manager = TurbineServices.getInstance(); + this.umDelegate = (TurbineUserManager)manager.getService(TurbineUserManager.ROLE); + + String userWrapperClass = conf.getString( + SecurityService.USER_WRAPPER_KEY, + SecurityService.USER_WRAPPER_DEFAULT); + +// String userClass = conf.getString( +// SecurityService.USER_KEY, +// SecurityService.USER_DEFAULT); + + try + { + factoryService = (FactoryService)manager.getService(FactoryService.ROLE); + + // check instantiation + + // should provide default constructor + TurbineUser turbineUser = umDelegate.getUserInstance(); + //(TurbineUser) factoryService.getInstance(userClass); + Object params[] = new Object[] { turbineUser }; + String signature[] = new String[] { TurbineUser.class.getName() }; + + // Just check if exceptions would occur + factoryService.getInstance(userWrapperClass, params, signature); + + this.setUserWrapperClass(userWrapperClass); + } + catch (Exception e) + { + throw new InitializationException("Failed to instantiate user wrapper class", e); + } + + } + + + /** + * Check whether a specified user's account exists. + * + * The login name is used for looking up the account. + * + * @param user The user to be checked. + * @return true if the specified account exists + * @throws DataBackendException if there was an error accessing the data backend. + */ + @Override + public boolean accountExists(User user) + throws DataBackendException + { + return umDelegate.checkExists(user); + } + + /** + * Check whether a specified user's account exists. + * + * The login name is used for looking up the account. + * + * @param userName The name of the user to be checked. + * @return true if the specified account exists + * @throws DataBackendException if there was an error accessing the data backend. + */ + @Override + public boolean accountExists(String userName) + throws DataBackendException + { + return umDelegate.checkExists(userName); + } + + /** + * Retrieve a user from persistent storage using username as the + * key. + * + * @param username the name of the user. + * @return an User object. + * @throws UnknownEntityException if the user's record does not + * exist in the database. + * @throws DataBackendException if there is a problem accessing the + * storage. + */ + @Override + public <U extends User> U retrieve(String username) + throws UnknownEntityException, DataBackendException + { + TurbineUser u = umDelegate.getUser(username); + return wrap(u); + } + + /** + * Retrieve a set of users that meet the specified criteria. + * + * As the keys for the criteria, you should use the constants that + * are defined in {@link User} interface, plus the names + * of the custom attributes you added to your user representation + * in the data storage. Use verbatim names of the attributes - + * without table name prefix in case of DB implementation. + * + * @param criteria The criteria of selection. + * @return a List of users meeting the criteria. + * @throws DataBackendException if there is a problem accessing the + * storage. + */ + @Override + public List<? extends User> retrieveList(Object criteria) + throws DataBackendException + { + UserSet uset = umDelegate.getAllUsers(); + List<User> userList = new ArrayList<User>(); + + for (org.apache.fulcrum.security.entity.User u : uset) + { + TurbineUser tu = (TurbineUser)u; + userList.add(wrap(tu)); + } + + return userList; + } + + /** + * Retrieve a user from persistent storage using username as the + * key, and authenticate the user. The implementation may chose + * to authenticate to the server as the user whose data is being + * retrieved. + * + * @param username the name of the user. + * @param password the user supplied password. + * @return an User object. + * @throws PasswordMismatchException if the supplied password was + * incorrect. + * @throws UnknownEntityException if the user's record does not + * exist in the database. + * @throws DataBackendException if there is a problem accessing the + * storage. + */ + @Override + public <U extends User> U retrieve(String username, String password) + throws PasswordMismatchException, UnknownEntityException, + DataBackendException + { + TurbineUser u = umDelegate.getUser(username, password); + return wrap(u); + } + + /** + * Save an User object to persistent storage. User's record is + * required to exist in the storage. + * + * @param user an User object to store. + * @throws UnknownEntityException if the user's record does not + * exist in the database. + * @throws DataBackendException if there is a problem accessing the + * storage. + */ + @Override + public void store(User user) + throws UnknownEntityException, DataBackendException + { + try + { + user.setObjectdata(ObjectUtils.serializeMap(user.getPermStorage())); + } + catch (Exception e) + { + throw new DataBackendException("Could not serialize permanent storage", e); + } + + umDelegate.saveUser(((TurbineUserDelegate)user).getUserDelegate()); + } + + /** + * Saves User data when the session is unbound. The user account is required + * to exist in the storage. + * + * LastLogin, AccessCounter, persistent pull tools, and any data stored + * in the permData hashtable that is not mapped to a column will be saved. + * + * @throws UnknownEntityException if the user's account does not + * exist in the database. + * @throws DataBackendException if there is a problem accessing the + * storage. + */ + @Override + public void saveOnSessionUnbind(User user) + throws UnknownEntityException, DataBackendException + { + store(user); + } + + /** + * Authenticate an User with the specified password. If authentication + * is successful the method returns nothing. If there are any problems, + * exception was thrown. + * + * @param user an User object to authenticate. + * @param password the user supplied password. + * @throws PasswordMismatchException if the supplied password was + * incorrect. + * @throws UnknownEntityException if the user's record does not + * exist in the database. + * @throws DataBackendException if there is a problem accessing the + * storage. + */ + @Override + public void authenticate(User user, String password) + throws PasswordMismatchException, UnknownEntityException, + DataBackendException + { + umDelegate.authenticate(user, password); + } + + /** + * Creates new user account with specified attributes. + * + * @param user the object describing account to be created. + * @param initialPassword The password to use for the object creation + * + * @throws DataBackendException if there was an error accessing the data backend. + * @throws EntityExistsException if the user account already exists. + */ + @Override + public void createAccount(User user, String initialPassword) + throws EntityExistsException, DataBackendException + { + umDelegate.addUser(user, initialPassword); + } + + /** + * Removes an user account from the system. + * + * @param user the object describing the account to be removed. + * @throws DataBackendException if there was an error accessing the data backend. + * @throws UnknownEntityException if the user account is not present. + */ + @Override + public void removeAccount(User user) + throws UnknownEntityException, DataBackendException + { + umDelegate.removeUser(user); + } + + /** + * Change the password for an User. + * + * @param user an User to change password for. + * @param oldPassword the current password supplied by the user. + * @param newPassword the current password requested by the user. + * @throws PasswordMismatchException if the supplied password was + * incorrect. + * @throws UnknownEntityException if the user's record does not + * exist in the database. + * @throws DataBackendException if there is a problem accessing the + * storage. + */ + @Override + public void changePassword(User user, String oldPassword, + String newPassword) + throws PasswordMismatchException, UnknownEntityException, + DataBackendException + { + umDelegate.changePassword( + ((TurbineUserDelegate)user).getUserDelegate(), + oldPassword, newPassword); + } + + /** + * Forcibly sets new password for an User. + * + * This is supposed by the administrator to change the forgotten or + * compromised passwords. Certain implementations of this feature + * would require administrative level access to the authenticating + * server / program. + * + * @param user an User to change password for. + * @param password the new password. + * @throws UnknownEntityException if the user's record does not + * exist in the database. + * @throws DataBackendException if there is a problem accessing the + * storage. + */ + @Override + public void forcePassword(User user, String password) + throws UnknownEntityException, DataBackendException + { + umDelegate.forcePassword(user, password); + } + + /** + * Constructs an User object to represent an anonymous user of the + * application. + * + * @return An anonymous Turbine User. + * @throws UnknownEntityException + * if the anonymous User object couldn't be constructed. + */ + @Override + public <T extends User> T getAnonymousUser() throws UnknownEntityException + { + TurbineUser u = umDelegate.getAnonymousUser(); + return wrap(u); + } + + /** + * Checks whether a passed user object matches the anonymous user pattern + * according to the configured user manager + * + * @param u a user object + * + * @return True if this is an anonymous user + * + */ + @Override + public boolean isAnonymousUser(User u) + { + return umDelegate.isAnonymousUser(u); + } + + /** + * Construct a blank User object. + * + * This method calls getUserClass, and then creates a new object using the + * default constructor. + * + * @return an object implementing User interface. + * @throws DataBackendException + * if the object could not be instantiated. + */ + @Override + public <T extends User> T getUserInstance() throws DataBackendException + { + TurbineUser u = umDelegate.getUserInstance(); + return wrap(u); + } + + /** + * Construct a blank User object. + * + * This method calls getUserClass, and then creates a new object using the + * default constructor. + * + * @param userName + * The name of the user. + * + * @return an object implementing User interface. + * @throws DataBackendException + * if the object could not be instantiated. + */ + @Override + public <T extends User> T getUserInstance(String userName) throws DataBackendException + { + TurbineUser u = umDelegate.getUserInstance(userName); + return wrap(u); + } + + /** + * Return a Class object representing the system's chosen implementation of + * of ACL interface. + * + * @return systems's chosen implementation of ACL interface. + * @throws UnknownEntityException + * if the implementation of ACL interface could not be + * determined, or does not exist. + */ + @Override + public <T extends AccessControlList> T getACL(User user) throws UnknownEntityException + { + return umDelegate.getACL(user); + } +} Modified: turbine/core/trunk/src/java/org/apache/turbine/services/security/SecurityService.java URL: http://svn.apache.org/viewvc/turbine/core/trunk/src/java/org/apache/turbine/services/security/SecurityService.java?rev=1812628&r1=1812627&r2=1812628&view=diff ============================================================================== --- turbine/core/trunk/src/java/org/apache/turbine/services/security/SecurityService.java (original) +++ turbine/core/trunk/src/java/org/apache/turbine/services/security/SecurityService.java Thu Oct 19 12:34:25 2017 @@ -73,13 +73,13 @@ public interface SecurityService */ String USER_MANAGER_DEFAULT = PassiveUserManager.class.getName(); - + /** * the key within services's properties for user implementation * classname (wrapper.class) */ String USER_WRAPPER_KEY = "wrapper.class"; - + /** * the default implementation of {@link User} interface * (org.apache.turbine.om.security.DefaultUserImpl) Modified: turbine/core/trunk/src/java/org/apache/turbine/services/ui/TurbineUIService.java URL: http://svn.apache.org/viewvc/turbine/core/trunk/src/java/org/apache/turbine/services/ui/TurbineUIService.java?rev=1812628&r1=1812627&r2=1812628&view=diff ============================================================================== --- turbine/core/trunk/src/java/org/apache/turbine/services/ui/TurbineUIService.java (original) +++ turbine/core/trunk/src/java/org/apache/turbine/services/ui/TurbineUIService.java Thu Oct 19 12:34:25 2017 @@ -1,543 +1,543 @@ -package org.apache.turbine.services.ui; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import java.io.File; -import java.io.InputStream; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.filefilter.DirectoryFileFilter; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.turbine.Turbine; -import org.apache.turbine.services.InitializationException; -import org.apache.turbine.services.TurbineBaseService; -import org.apache.turbine.services.TurbineServices; -import org.apache.turbine.services.pull.PullService; -import org.apache.turbine.services.pull.tools.UITool; -import org.apache.turbine.services.servlet.ServletService; -import org.apache.turbine.util.ServerData; -import org.apache.turbine.util.uri.DataURI; - -/** - * The UI service provides for shared access to User Interface (skin) files, - * as well as the ability for non-default skin files to inherit properties from - * a default skin. Use TurbineUI to access skin properties from your screen - * classes and action code. UITool is provided as a pull tool for accessing - * skin properties from your templates. - * - * @author <a href="mailto:[email protected]">Jason van Zyl</a> - * @author <a href="mailto:[email protected]">James Coltman</a> - * @author <a href="mailto:[email protected]">Henning P. Schmiedehausen</a> - * @author <a href="mailto:[email protected]">Scott Eade</a> - * @author <a href="[email protected]">Thomas Vandahl</a> - * @version $Id$ - * @see UIService - * @see UITool - */ -public class TurbineUIService - extends TurbineBaseService - implements UIService -{ - /** Logging. */ - private static Log log = LogFactory.getLog(TurbineUIService.class); - - /** - * The location of the skins within the application resources directory. - */ - private static final String SKINS_DIRECTORY = "/ui/skins"; - - /** - * The name of the directory where images are stored for this skin. - */ - private static final String IMAGES_DIRECTORY = "/images"; - - /** - * Property tag for the default skin that is to be used for the web - * application. - */ - private static final String SKIN_PROPERTY = "tool.ui.skin"; - - /** - * Property tag for the image directory inside the skin that is to be used - * for the web application. - */ - private static final String IMAGEDIR_PROPERTY = "tool.ui.dir.image"; - - /** - * Property tag for the skin directory that is to be used for the web - * application. - */ - private static final String SKINDIR_PROPERTY = "tool.ui.dir.skin"; - - /** - * Property tag for the css file that is to be used for the web application. - */ - private static final String CSS_PROPERTY = "tool.ui.css"; - - /** - * Property tag for indicating if relative links are wanted for the web - * application. - */ - private static final String RELATIVE_PROPERTY = "tool.ui.want.relative"; - - /** - * Default skin name. This name refers to a directory in the - * WEBAPP/resources/ui/skins directory. There is a file called skin.props - * which contains the name/value pairs to be made available via the skin. - */ - public static final String SKIN_PROPERTY_DEFAULT = "default"; - - /** - * The skins directory, qualified by the resources directory (which is - * relative to the webapp context). This is used for constructing URIs and - * for retrieving skin files. - */ - private String skinsDirectory; - - /** - * The file within the skin directory that contains the name/value pairs for - * the skin. - */ - private static final String SKIN_PROPS_FILE = "skin.props"; - - /** - * The file name for the skin style sheet. - */ - private static final String DEFAULT_SKIN_CSS_FILE = "skin.css"; - - /** - * The servlet service. - */ - private ServletService servletService; - - /** - * The directory within the skin directory that contains the skin images. - */ - private String imagesDirectory; - - /** - * The name of the css file within the skin directory. - */ - private String cssFile; - - /** - * The flag that determines if the links that are returned are are absolute - * or relative. - */ - private boolean wantRelative = false; - - /** - * The skin Properties store. - */ - private ConcurrentHashMap<String, Properties> skins = new ConcurrentHashMap<String, Properties>(); - - /** - * Refresh the service by clearing all skins. - */ - @Override - public void refresh() - { - clearSkins(); - } - - /** - * Refresh a particular skin by clearing it. - * - * @param skinName the name of the skin to clear. - */ - @Override - public void refresh(String skinName) - { - clearSkin(skinName); - } - - /** - * Retrieve the Properties for a specific skin. If they are not yet loaded - * they will be. If the specified skin does not exist properties for the - * default skin configured for the webapp will be returned and an error - * level message will be written to the log. If the webapp skin does not - * exist the default skin will be used and id that doesn't exist an empty - * Properties will be returned. - * - * @param skinName the name of the skin whose properties are to be - * retrieved. - * @return the Properties for the named skin or the properties for the - * default skin configured for the webapp if the named skin does not exist. - */ - private Properties getSkinProperties(String skinName) - { - Properties skinProperties = skins.get(skinName); - return null != skinProperties ? skinProperties : loadSkin(skinName); - } - - /** - * Retrieve a skin property from the named skin. If the property is not - * defined in the named skin the value for the default skin will be - * provided. If the named skin does not exist then the skin configured for - * the webapp will be used. If the webapp skin does not exist the default - * skin will be used. If the default skin does not exist then - * <code>null</code> will be returned. - * - * @param skinName the name of the skin to retrieve the property from. - * @param key the key to retrieve from the skin. - * @return the value of the property for the named skin (defaulting to the - * default skin), the webapp skin, the default skin or <code>null</code>, - * depending on whether or not the property or skins exist. - */ - @Override - public String get(String skinName, String key) - { - Properties skinProperties = getSkinProperties(skinName); - return skinProperties.getProperty(key); - } - - /** - * Retrieve a skin property from the default skin for the webapp. If the - * property is not defined in the webapp skin the value for the default skin - * will be provided. If the webapp skin does not exist the default skin - * will be used. If the default skin does not exist then <code>null</code> - * will be returned. - * - * @param key the key to retrieve. - * @return the value of the property for the webapp skin (defaulting to the - * default skin), the default skin or <code>null</code>, depending on - * whether or not the property or skins exist. - */ - @Override - public String get(String key) - { - return get(getWebappSkinName(), key); - } - - /** - * Provide access to the list of available skin names. - * - * @return the available skin names. - */ - @Override - public String[] getSkinNames() - { - File skinsDir = new File(servletService.getRealPath(skinsDirectory)); - return skinsDir.list(DirectoryFileFilter.INSTANCE); - } - - /** - * Clear the map of stored skins. - */ - private void clearSkins() - { - skins.clear(); - log.debug("All skins were cleared."); - } - - /** - * Clear a particular skin from the map of stored skins. - * - * @param skinName the name of the skin to clear. - */ - private void clearSkin(String skinName) - { - if (!skinName.equals(SKIN_PROPERTY_DEFAULT)) - { - skins.remove(SKIN_PROPERTY_DEFAULT); - } - skins.remove(skinName); - log.debug("The skin \"" + skinName - + "\" was cleared (will also clear \"default\" skin)."); - } - - /** - * Load the specified skin. - * - * @param skinName the name of the skin to load. - * @return the Properties for the named skin if it exists, or the skin - * configured for the web application if it does not exist, or the default - * skin if that does not exist, or an empty Parameters object if even that - * cannot be found. - */ - private Properties loadSkin(String skinName) - { - Properties defaultSkinProperties = null; - - if (!StringUtils.equals(skinName, SKIN_PROPERTY_DEFAULT)) - { - defaultSkinProperties = getSkinProperties(SKIN_PROPERTY_DEFAULT); - } - - // The following line is okay even for default. - Properties skinProperties = new Properties(defaultSkinProperties); - - StringBuilder sb = new StringBuilder(); - sb.append('/').append(skinsDirectory); - sb.append('/').append(skinName); - sb.append('/').append(SKIN_PROPS_FILE); - if (log.isDebugEnabled()) - { - log.debug("Loading selected skin from: " + sb.toString()); - } - - InputStream is = null; - - try - { - // This will NPE if the directory associated with the skin does not - // exist, but it is handled correctly below. - is = servletService.getResourceAsStream(sb.toString()); - skinProperties.load(is); - } - catch (Exception e) - { - log.error("Cannot load skin: " + skinName + ", from: " - + sb.toString(), e); - if (!StringUtils.equals(skinName, getWebappSkinName()) - && !StringUtils.equals(skinName, SKIN_PROPERTY_DEFAULT)) - { - log.error("Attempting to return the skin configured for " - + "webapp instead of " + skinName); - return getSkinProperties(getWebappSkinName()); - } - else if (!StringUtils.equals(skinName, SKIN_PROPERTY_DEFAULT)) - { - log.error("Return the default skin instead of " + skinName); - return skinProperties; // Already contains the default skin. - } - else - { - log.error("No skins available - returning an empty Properties"); - return new Properties(); - } - } - finally - { - IOUtils.closeQuietly(is); - } - - // Replace in skins HashMap - skins.put(skinName, skinProperties); - - return skinProperties; - } - - /** - * Get the name of the default skin name for the web application from the - * TurbineResources.properties file. If the property is not present the - * name of the default skin will be returned. Note that the web application - * skin name may be something other than default, in which case its - * properties will default to the skin with the name "default". - * - * @return the name of the default skin for the web application. - */ - @Override - public String getWebappSkinName() - { - return Turbine.getConfiguration() - .getString(SKIN_PROPERTY, SKIN_PROPERTY_DEFAULT); - } - - /** - * Retrieve the URL for an image that is part of a skin. The images are - * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory. - * - * <p>Use this if for some reason your server name, server scheme, or server - * port change on a per request basis. I'm not sure if this would happen in - * a load balanced situation. I think in most cases the image(String image) - * method would probably be enough, but I'm not absolutely positive. - * - * @param skinName the name of the skin to retrieve the image from. - * @param imageId the id of the image whose URL will be generated. - * @param serverData the serverData to use as the basis for the URL. - */ - @Override - public String image(String skinName, String imageId, ServerData serverData) - { - return getSkinResource(serverData, skinName, imagesDirectory, imageId); - } - - /** - * Retrieve the URL for an image that is part of a skin. The images are - * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory. - * - * @param skinName the name of the skin to retrieve the image from. - * @param imageId the id of the image whose URL will be generated. - */ - @Override - public String image(String skinName, String imageId) - { - return image(skinName, imageId, Turbine.getDefaultServerData()); - } - - /** - * Retrieve the URL for the style sheet that is part of a skin. The style is - * stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the - * filename skin.css - * - * <p>Use this if for some reason your server name, server scheme, or server - * port change on a per request basis. I'm not sure if this would happen in - * a load balanced situation. I think in most cases the style() method would - * probably be enough, but I'm not absolutely positive. - * - * @param skinName the name of the skin to retrieve the style sheet from. - * @param serverData the serverData to use as the basis for the URL. - */ - @Override - public String getStylecss(String skinName, ServerData serverData) - { - return getSkinResource(serverData, skinName, null, cssFile); - } - - /** - * Retrieve the URL for the style sheet that is part of a skin. The style is - * stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the - * filename skin.css - * - * @param skinName the name of the skin to retrieve the style sheet from. - */ - @Override - public String getStylecss(String skinName) - { - return getStylecss(skinName, Turbine.getDefaultServerData()); - } - - /** - * Retrieve the URL for a given script that is part of a skin. The script is - * stored in the WEBAPP/resources/ui/skins/[SKIN] directory. - * - * <p>Use this if for some reason your server name, server scheme, or server - * port change on a per request basis. I'm not sure if this would happen in - * a load balanced situation. I think in most cases the style() method would - * probably be enough, but I'm not absolutely positive. - * - * @param skinName the name of the skin to retrieve the image from. - * @param filename the name of the script file. - * @param serverData the serverData to use as the basis for the URL. - */ - @Override - public String getScript(String skinName, String filename, - ServerData serverData) - { - return getSkinResource(serverData, skinName, null, filename); - } - - /** - * Retrieve the URL for a given script that is part of a skin. The script is - * stored in the WEBAPP/resources/ui/skins/[SKIN] directory. - * - * @param skinName the name of the skin to retrieve the image from. - * @param filename the name of the script file. - */ - @Override - public String getScript(String skinName, String filename) - { - return getScript(skinName, filename, Turbine.getDefaultServerData()); - } - - private String stripSlashes(final String path) - { - if (StringUtils.isEmpty(path)) - { - return ""; - } - - String ret = path; - int len = ret.length() - 1; - - if (ret.charAt(len) == '/') - { - ret = ret.substring(0, len); - } - - if (len > 0 && ret.charAt(0) == '/') - { - ret = ret.substring(1); - } - - return ret; - } - - /** - * Construct the URL to the skin resource. - * - * @param serverData the serverData to use as the basis for the URL. - * @param skinName the name of the skin. - * @param subDir the sub-directory in which the resource resides or - * <code>null</code> if it is in the root directory of the skin. - * @param resourceName the name of the resource to be retrieved. - * @return the path to the resource. - */ - private String getSkinResource(ServerData serverData, String skinName, - String subDir, String resourceName) - { - StringBuilder sb = new StringBuilder(skinsDirectory); - sb.append("/").append(skinName); - if (subDir != null) - { - sb.append("/").append(subDir); - } - sb.append("/").append(stripSlashes(resourceName)); - - DataURI du = new DataURI(serverData); - du.setScriptName(sb.toString()); - return wantRelative ? du.getRelativeLink() : du.getAbsoluteLink(); - } - - // ---- Service initilization ------------------------------------------ - - /** - * Initializes the service. - */ - @Override - public void init() throws InitializationException - { - Configuration cfg = Turbine.getConfiguration(); - - servletService = (ServletService)TurbineServices.getInstance().getService(ServletService.SERVICE_NAME); - PullService pullService = (PullService)TurbineServices.getInstance().getService(PullService.SERVICE_NAME); - // Get the resources directory that is specified in the TR.props or - // default to "resources", relative to the webapp. - StringBuilder sb = new StringBuilder(); - sb.append(stripSlashes(pullService.getResourcesDirectory())); - sb.append("/"); - sb.append(stripSlashes( - cfg.getString(SKINDIR_PROPERTY, SKINS_DIRECTORY))); - skinsDirectory = sb.toString(); - - imagesDirectory = stripSlashes( - cfg.getString(IMAGEDIR_PROPERTY, IMAGES_DIRECTORY)); - cssFile = cfg.getString(CSS_PROPERTY, DEFAULT_SKIN_CSS_FILE); - wantRelative = cfg.getBoolean(RELATIVE_PROPERTY, false); - - setInit(true); - } - - /** - * Returns to uninitialized state. - */ - @Override - public void shutdown() - { - clearSkins(); - setInit(false); - } -} +package org.apache.turbine.services.ui; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.io.InputStream; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.commons.configuration.Configuration; +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.filefilter.DirectoryFileFilter; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.turbine.Turbine; +import org.apache.turbine.services.InitializationException; +import org.apache.turbine.services.TurbineBaseService; +import org.apache.turbine.services.TurbineServices; +import org.apache.turbine.services.pull.PullService; +import org.apache.turbine.services.pull.tools.UITool; +import org.apache.turbine.services.servlet.ServletService; +import org.apache.turbine.util.ServerData; +import org.apache.turbine.util.uri.DataURI; + +/** + * The UI service provides for shared access to User Interface (skin) files, + * as well as the ability for non-default skin files to inherit properties from + * a default skin. Use TurbineUI to access skin properties from your screen + * classes and action code. UITool is provided as a pull tool for accessing + * skin properties from your templates. + * + * @author <a href="mailto:[email protected]">Jason van Zyl</a> + * @author <a href="mailto:[email protected]">James Coltman</a> + * @author <a href="mailto:[email protected]">Henning P. Schmiedehausen</a> + * @author <a href="mailto:[email protected]">Scott Eade</a> + * @author <a href="[email protected]">Thomas Vandahl</a> + * @version $Id$ + * @see UIService + * @see UITool + */ +public class TurbineUIService + extends TurbineBaseService + implements UIService +{ + /** Logging. */ + private static Log log = LogFactory.getLog(TurbineUIService.class); + + /** + * The location of the skins within the application resources directory. + */ + private static final String SKINS_DIRECTORY = "/ui/skins"; + + /** + * The name of the directory where images are stored for this skin. + */ + private static final String IMAGES_DIRECTORY = "/images"; + + /** + * Property tag for the default skin that is to be used for the web + * application. + */ + private static final String SKIN_PROPERTY = "tool.ui.skin"; + + /** + * Property tag for the image directory inside the skin that is to be used + * for the web application. + */ + private static final String IMAGEDIR_PROPERTY = "tool.ui.dir.image"; + + /** + * Property tag for the skin directory that is to be used for the web + * application. + */ + private static final String SKINDIR_PROPERTY = "tool.ui.dir.skin"; + + /** + * Property tag for the css file that is to be used for the web application. + */ + private static final String CSS_PROPERTY = "tool.ui.css"; + + /** + * Property tag for indicating if relative links are wanted for the web + * application. + */ + private static final String RELATIVE_PROPERTY = "tool.ui.want.relative"; + + /** + * Default skin name. This name refers to a directory in the + * WEBAPP/resources/ui/skins directory. There is a file called skin.props + * which contains the name/value pairs to be made available via the skin. + */ + public static final String SKIN_PROPERTY_DEFAULT = "default"; + + /** + * The skins directory, qualified by the resources directory (which is + * relative to the webapp context). This is used for constructing URIs and + * for retrieving skin files. + */ + private String skinsDirectory; + + /** + * The file within the skin directory that contains the name/value pairs for + * the skin. + */ + private static final String SKIN_PROPS_FILE = "skin.props"; + + /** + * The file name for the skin style sheet. + */ + private static final String DEFAULT_SKIN_CSS_FILE = "skin.css"; + + /** + * The servlet service. + */ + private ServletService servletService; + + /** + * The directory within the skin directory that contains the skin images. + */ + private String imagesDirectory; + + /** + * The name of the css file within the skin directory. + */ + private String cssFile; + + /** + * The flag that determines if the links that are returned are are absolute + * or relative. + */ + private boolean wantRelative = false; + + /** + * The skin Properties store. + */ + private ConcurrentHashMap<String, Properties> skins = new ConcurrentHashMap<String, Properties>(); + + /** + * Refresh the service by clearing all skins. + */ + @Override + public void refresh() + { + clearSkins(); + } + + /** + * Refresh a particular skin by clearing it. + * + * @param skinName the name of the skin to clear. + */ + @Override + public void refresh(String skinName) + { + clearSkin(skinName); + } + + /** + * Retrieve the Properties for a specific skin. If they are not yet loaded + * they will be. If the specified skin does not exist properties for the + * default skin configured for the webapp will be returned and an error + * level message will be written to the log. If the webapp skin does not + * exist the default skin will be used and id that doesn't exist an empty + * Properties will be returned. + * + * @param skinName the name of the skin whose properties are to be + * retrieved. + * @return the Properties for the named skin or the properties for the + * default skin configured for the webapp if the named skin does not exist. + */ + private Properties getSkinProperties(String skinName) + { + Properties skinProperties = skins.get(skinName); + return null != skinProperties ? skinProperties : loadSkin(skinName); + } + + /** + * Retrieve a skin property from the named skin. If the property is not + * defined in the named skin the value for the default skin will be + * provided. If the named skin does not exist then the skin configured for + * the webapp will be used. If the webapp skin does not exist the default + * skin will be used. If the default skin does not exist then + * <code>null</code> will be returned. + * + * @param skinName the name of the skin to retrieve the property from. + * @param key the key to retrieve from the skin. + * @return the value of the property for the named skin (defaulting to the + * default skin), the webapp skin, the default skin or <code>null</code>, + * depending on whether or not the property or skins exist. + */ + @Override + public String get(String skinName, String key) + { + Properties skinProperties = getSkinProperties(skinName); + return skinProperties.getProperty(key); + } + + /** + * Retrieve a skin property from the default skin for the webapp. If the + * property is not defined in the webapp skin the value for the default skin + * will be provided. If the webapp skin does not exist the default skin + * will be used. If the default skin does not exist then <code>null</code> + * will be returned. + * + * @param key the key to retrieve. + * @return the value of the property for the webapp skin (defaulting to the + * default skin), the default skin or <code>null</code>, depending on + * whether or not the property or skins exist. + */ + @Override + public String get(String key) + { + return get(getWebappSkinName(), key); + } + + /** + * Provide access to the list of available skin names. + * + * @return the available skin names. + */ + @Override + public String[] getSkinNames() + { + File skinsDir = new File(servletService.getRealPath(skinsDirectory)); + return skinsDir.list(DirectoryFileFilter.INSTANCE); + } + + /** + * Clear the map of stored skins. + */ + private void clearSkins() + { + skins.clear(); + log.debug("All skins were cleared."); + } + + /** + * Clear a particular skin from the map of stored skins. + * + * @param skinName the name of the skin to clear. + */ + private void clearSkin(String skinName) + { + if (!skinName.equals(SKIN_PROPERTY_DEFAULT)) + { + skins.remove(SKIN_PROPERTY_DEFAULT); + } + skins.remove(skinName); + log.debug("The skin \"" + skinName + + "\" was cleared (will also clear \"default\" skin)."); + } + + /** + * Load the specified skin. + * + * @param skinName the name of the skin to load. + * @return the Properties for the named skin if it exists, or the skin + * configured for the web application if it does not exist, or the default + * skin if that does not exist, or an empty Parameters object if even that + * cannot be found. + */ + private Properties loadSkin(String skinName) + { + Properties defaultSkinProperties = null; + + if (!StringUtils.equals(skinName, SKIN_PROPERTY_DEFAULT)) + { + defaultSkinProperties = getSkinProperties(SKIN_PROPERTY_DEFAULT); + } + + // The following line is okay even for default. + Properties skinProperties = new Properties(defaultSkinProperties); + + StringBuilder sb = new StringBuilder(); + sb.append('/').append(skinsDirectory); + sb.append('/').append(skinName); + sb.append('/').append(SKIN_PROPS_FILE); + if (log.isDebugEnabled()) + { + log.debug("Loading selected skin from: " + sb.toString()); + } + + InputStream is = null; + + try + { + // This will NPE if the directory associated with the skin does not + // exist, but it is handled correctly below. + is = servletService.getResourceAsStream(sb.toString()); + skinProperties.load(is); + } + catch (Exception e) + { + log.error("Cannot load skin: " + skinName + ", from: " + + sb.toString(), e); + if (!StringUtils.equals(skinName, getWebappSkinName()) + && !StringUtils.equals(skinName, SKIN_PROPERTY_DEFAULT)) + { + log.error("Attempting to return the skin configured for " + + "webapp instead of " + skinName); + return getSkinProperties(getWebappSkinName()); + } + else if (!StringUtils.equals(skinName, SKIN_PROPERTY_DEFAULT)) + { + log.error("Return the default skin instead of " + skinName); + return skinProperties; // Already contains the default skin. + } + else + { + log.error("No skins available - returning an empty Properties"); + return new Properties(); + } + } + finally + { + IOUtils.closeQuietly(is); + } + + // Replace in skins HashMap + skins.put(skinName, skinProperties); + + return skinProperties; + } + + /** + * Get the name of the default skin name for the web application from the + * TurbineResources.properties file. If the property is not present the + * name of the default skin will be returned. Note that the web application + * skin name may be something other than default, in which case its + * properties will default to the skin with the name "default". + * + * @return the name of the default skin for the web application. + */ + @Override + public String getWebappSkinName() + { + return Turbine.getConfiguration() + .getString(SKIN_PROPERTY, SKIN_PROPERTY_DEFAULT); + } + + /** + * Retrieve the URL for an image that is part of a skin. The images are + * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory. + * + * <p>Use this if for some reason your server name, server scheme, or server + * port change on a per request basis. I'm not sure if this would happen in + * a load balanced situation. I think in most cases the image(String image) + * method would probably be enough, but I'm not absolutely positive. + * + * @param skinName the name of the skin to retrieve the image from. + * @param imageId the id of the image whose URL will be generated. + * @param serverData the serverData to use as the basis for the URL. + */ + @Override + public String image(String skinName, String imageId, ServerData serverData) + { + return getSkinResource(serverData, skinName, imagesDirectory, imageId); + } + + /** + * Retrieve the URL for an image that is part of a skin. The images are + * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory. + * + * @param skinName the name of the skin to retrieve the image from. + * @param imageId the id of the image whose URL will be generated. + */ + @Override + public String image(String skinName, String imageId) + { + return image(skinName, imageId, Turbine.getDefaultServerData()); + } + + /** + * Retrieve the URL for the style sheet that is part of a skin. The style is + * stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the + * filename skin.css + * + * <p>Use this if for some reason your server name, server scheme, or server + * port change on a per request basis. I'm not sure if this would happen in + * a load balanced situation. I think in most cases the style() method would + * probably be enough, but I'm not absolutely positive. + * + * @param skinName the name of the skin to retrieve the style sheet from. + * @param serverData the serverData to use as the basis for the URL. + */ + @Override + public String getStylecss(String skinName, ServerData serverData) + { + return getSkinResource(serverData, skinName, null, cssFile); + } + + /** + * Retrieve the URL for the style sheet that is part of a skin. The style is + * stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the + * filename skin.css + * + * @param skinName the name of the skin to retrieve the style sheet from. + */ + @Override + public String getStylecss(String skinName) + { + return getStylecss(skinName, Turbine.getDefaultServerData()); + } + + /** + * Retrieve the URL for a given script that is part of a skin. The script is + * stored in the WEBAPP/resources/ui/skins/[SKIN] directory. + * + * <p>Use this if for some reason your server name, server scheme, or server + * port change on a per request basis. I'm not sure if this would happen in + * a load balanced situation. I think in most cases the style() method would + * probably be enough, but I'm not absolutely positive. + * + * @param skinName the name of the skin to retrieve the image from. + * @param filename the name of the script file. + * @param serverData the serverData to use as the basis for the URL. + */ + @Override + public String getScript(String skinName, String filename, + ServerData serverData) + { + return getSkinResource(serverData, skinName, null, filename); + } + + /** + * Retrieve the URL for a given script that is part of a skin. The script is + * stored in the WEBAPP/resources/ui/skins/[SKIN] directory. + * + * @param skinName the name of the skin to retrieve the image from. + * @param filename the name of the script file. + */ + @Override + public String getScript(String skinName, String filename) + { + return getScript(skinName, filename, Turbine.getDefaultServerData()); + } + + private String stripSlashes(final String path) + { + if (StringUtils.isEmpty(path)) + { + return ""; + } + + String ret = path; + int len = ret.length() - 1; + + if (ret.charAt(len) == '/') + { + ret = ret.substring(0, len); + } + + if (len > 0 && ret.charAt(0) == '/') + { + ret = ret.substring(1); + } + + return ret; + } + + /** + * Construct the URL to the skin resource. + * + * @param serverData the serverData to use as the basis for the URL. + * @param skinName the name of the skin. + * @param subDir the sub-directory in which the resource resides or + * <code>null</code> if it is in the root directory of the skin. + * @param resourceName the name of the resource to be retrieved. + * @return the path to the resource. + */ + private String getSkinResource(ServerData serverData, String skinName, + String subDir, String resourceName) + { + StringBuilder sb = new StringBuilder(skinsDirectory); + sb.append("/").append(skinName); + if (subDir != null) + { + sb.append("/").append(subDir); + } + sb.append("/").append(stripSlashes(resourceName)); + + DataURI du = new DataURI(serverData); + du.setScriptName(sb.toString()); + return wantRelative ? du.getRelativeLink() : du.getAbsoluteLink(); + } + + // ---- Service initilization ------------------------------------------ + + /** + * Initializes the service. + */ + @Override + public void init() throws InitializationException + { + Configuration cfg = Turbine.getConfiguration(); + + servletService = (ServletService)TurbineServices.getInstance().getService(ServletService.SERVICE_NAME); + PullService pullService = (PullService)TurbineServices.getInstance().getService(PullService.SERVICE_NAME); + // Get the resources directory that is specified in the TR.props or + // default to "resources", relative to the webapp. + StringBuilder sb = new StringBuilder(); + sb.append(stripSlashes(pullService.getResourcesDirectory())); + sb.append("/"); + sb.append(stripSlashes( + cfg.getString(SKINDIR_PROPERTY, SKINS_DIRECTORY))); + skinsDirectory = sb.toString(); + + imagesDirectory = stripSlashes( + cfg.getString(IMAGEDIR_PROPERTY, IMAGES_DIRECTORY)); + cssFile = cfg.getString(CSS_PROPERTY, DEFAULT_SKIN_CSS_FILE); + wantRelative = cfg.getBoolean(RELATIVE_PROPERTY, false); + + setInit(true); + } + + /** + * Returns to uninitialized state. + */ + @Override + public void shutdown() + { + clearSkins(); + setInit(false); + } +}
