View Javadoc

1   /*
2    * Copyright (c) 2007, James Leigh All rights reserved.
3    * 
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted provided that the following conditions are met:
6    * 
7    * - Redistributions of source code must retain the above copyright notice, this
8    *   list of conditions and the following disclaimer.
9    * - Redistributions in binary form must reproduce the above copyright notice,
10   *   this list of conditions and the following disclaimer in the documentation
11   *   and/or other materials provided with the distribution. 
12   * - Neither the name of the openrdf.org nor the names of its contributors may
13   *   be used to endorse or promote products derived from this software without
14   *   specific prior written permission.
15   * 
16   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26   * POSSIBILITY OF SUCH DAMAGE.
27   * 
28   */
29  package org.openrdf.elmo.tapestry;
30  
31  import java.util.Collection;
32  import java.util.Locale;
33  import java.util.concurrent.ConcurrentHashMap;
34  import java.util.concurrent.ConcurrentMap;
35  
36  import org.apache.hivemind.service.ThreadCleanupListener;
37  import org.apache.hivemind.service.ThreadEventNotifier;
38  import org.apache.hivemind.service.ThreadLocale;
39  import org.openrdf.elmo.Entity;
40  import org.openrdf.elmo.RoleMapper;
41  import org.openrdf.elmo.dynacode.ClassFactory;
42  import org.openrdf.elmo.exceptions.ElmoPersistException;
43  import org.openrdf.elmo.impl.ElmoEntityCompositor;
44  import org.openrdf.elmo.impl.ElmoMapperClassFactory;
45  import org.openrdf.elmo.impl.InstanceBehaviourFactory;
46  import org.openrdf.elmo.sesame.SesameEntitySupport;
47  import org.openrdf.elmo.sesame.SesameLiteralManager;
48  import org.openrdf.elmo.sesame.SesameManager;
49  import org.openrdf.elmo.sesame.SesamePropertyFactory;
50  import org.openrdf.elmo.sesame.SesameResourceManager;
51  import org.openrdf.elmo.sesame.SesameRoleMapperFactory;
52  import org.openrdf.model.URI;
53  import org.openrdf.model.ValueFactory;
54  import org.openrdf.query.QueryLanguage;
55  import org.openrdf.repository.Repository;
56  import org.openrdf.repository.RepositoryException;
57  import org.openrdf.repository.contextaware.ContextAwareConnection;
58  
59  /**
60   * Convents the properties used in a HiveMind repository to SesameBeanManager's
61   * properties. This class converts repository -> connection, threadLocale ->
62   * locale, QueryLanguageName -> QueryLanguage. This class also closesthe
63   * connection when the thread is discarded.
64   * 
65   * @author James Leigh
66   * 
67   */
68  public class HiveMindSesameManager extends SesameManager implements
69  		ThreadCleanupListener {
70  
71  	private ConcurrentMap<Locale, String> languages;
72  
73  	private Repository repository;
74  
75  	private ThreadEventNotifier threadEventNotifier;
76  
77  	private ThreadLocale threadLocale;
78  
79  	private QueryLanguage ql = QueryLanguage.SPARQL;
80  
81  	private Collection<Class<?>> roles;
82  
83  	@SuppressWarnings("unchecked")
84  	public HiveMindSesameManager() {
85  		languages = new ConcurrentHashMap<Locale, String>();
86  	}
87  
88  	/**
89  	 * Registers all the given roles with their default subject type.
90  	 * 
91  	 * @param roles
92  	 */
93  	public void setRoles(Collection<Class<?>> roles) {
94  		this.roles = roles;
95  	}
96  
97  	public void setRepository(Repository repository) throws RepositoryException {
98  		this.repository = repository;
99  		ContextAwareConnection conn = new ContextAwareConnection(repository);
100 		conn.setQueryLanguage(ql);
101 		setConnection(conn);
102 	}
103 
104 	public void setQueryLanguageName(String ql) {
105 		this.ql = QueryLanguage.valueOf(ql);
106 		if (getConnection() != null) {
107 			getConnection().setQueryLanguage(this.ql);
108 		}
109 	}
110 
111 	public void setThreadEventNotifier(ThreadEventNotifier threadEventNotifier) {
112 		this.threadEventNotifier = threadEventNotifier;
113 		threadEventNotifier.addThreadCleanupListener(this);
114 	}
115 
116 	public void setThreadLocale(ThreadLocale threadLocale) {
117 		this.threadLocale = threadLocale;
118 	}
119 
120 	public void init() throws RepositoryException {
121 		ClassLoader cl = Thread.currentThread().getContextClassLoader();
122 		if (cl == null)
123 			cl = getClass().getClassLoader();
124 		ClassFactory definer = new ClassFactory(cl);
125 		ValueFactory vf = repository.getValueFactory();
126 		SesameLiteralManager literalManager = new SesameLiteralManager(vf);
127 		literalManager.setClassLoader(cl);
128 		SesameRoleMapperFactory factory = new SesameRoleMapperFactory(vf);
129 		factory.setClassLoader(cl);
130 		RoleMapper<URI> mapper = factory.createRoleMapper();
131 		mapper.recordRole(SesameEntitySupport.class);
132 		ElmoMapperClassFactory propertyMapper = new ElmoMapperClassFactory();
133 		propertyMapper.setElmoPropertyFactoryClass(SesamePropertyFactory.class);
134 		propertyMapper.setClassDefiner(definer);
135 		ElmoEntityCompositor resolver = new ElmoEntityCompositor();
136 		resolver.setClassDefiner(definer);
137 		resolver.setBehaviourClassResolver(propertyMapper);
138 		resolver.addFactoryClass(InstanceBehaviourFactory.class);
139 		resolver.addFactoryClass(InstanceBehaviourFactory.class, Entity.class);
140 		if (roles != null) {
141 			for (Class<?> r : roles) {
142 				mapper.recordRole(r);
143 			}
144 		}
145 		ContextAwareConnection conn = new ContextAwareConnection(repository);
146 		conn.setQueryLanguage(ql);
147 		SesameResourceManager rolesManager = new SesameResourceManager();
148 		rolesManager.setConnection(conn);
149 		rolesManager.setValueFactory(repository.getValueFactory());
150 		rolesManager.setRoleMapper(mapper);
151 		super.setConnection(conn);
152 		super.setElmoClassResolver(resolver);
153 		super.setLiteralManager(literalManager);
154 		super.setResourceManager(rolesManager);
155 	}
156 
157 	public void threadDidCleanup() {
158 		clear();
159 		try {
160 			ContextAwareConnection connection = getConnection();
161 			if (connection != null)
162 				connection.close();
163 		} catch (RepositoryException e) {
164 			throw new ElmoPersistException(e);
165 		}
166 		threadEventNotifier.addThreadCleanupListener(this);
167 	}
168 
169 	@Override
170 	public Locale getLocale() {
171 		if (threadLocale == null)
172 			return super.getLocale();
173 		return threadLocale.getLocale();
174 	}
175 
176 	@Override
177 	public String getLanguage() {
178 		if (threadLocale == null)
179 			return super.getLanguage();
180 		Locale locale = threadLocale.getLocale();
181 		if (languages.containsKey(locale))
182 			return languages.get(locale);
183 		String l = convertLocaleToLanguage(locale);
184 		String o = languages.putIfAbsent(locale, l);
185 		if (o != null) {
186 			l = o;
187 		}
188 		return l;
189 	}
190 
191 	@Override
192 	public boolean isOpen() {
193 		return true;
194 	}
195 
196 	private String convertLocaleToLanguage(Locale locale) {
197 		String l = locale.toString().replace('_', '-');
198 		return l.toLowerCase(locale);
199 	}
200 
201 }