001: /**
002: * Speedo: an implementation of JDO compliant personality on top of JORM generic
003: * I/O sub-system.
004: * Copyright (C) 2001-2004 France Telecom R&D
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: *
021: *
022: * Contact: speedo@objectweb.org
023: *
024: */package org.objectweb.speedo.sequence.lib;
025:
026: import java.util.HashMap;
027: import java.util.Map;
028:
029: import org.objectweb.fractal.api.control.BindingController;
030: import org.objectweb.jorm.api.PClassMapping;
031: import org.objectweb.jorm.api.PException;
032: import org.objectweb.jorm.api.PMapper;
033: import org.objectweb.jorm.facility.naming.generator.LongGenMgr;
034: import org.objectweb.jorm.facility.naming.generator.LongGenMgrRegistry;
035: import org.objectweb.jorm.facility.naming.rdbsequence.RdbSequenceLongGen;
036: import org.objectweb.jorm.mapper.rdb.lib.PMapperRdb;
037: import org.objectweb.speedo.sequence.api.SpeedoSequenceItf;
038: import org.objectweb.speedo.sequence.lib.SpeedoSequence;
039: import org.objectweb.speedo.api.ExceptionHelper;
040: import org.objectweb.speedo.pm.api.POManagerFactoryItf;
041: import org.objectweb.speedo.sequence.api.SequenceManager;
042: import org.objectweb.util.monolog.api.BasicLevel;
043: import org.objectweb.util.monolog.api.Logger;
044:
045: /**
046: * The SpeedoSequenceManager
047: * @author Y.Bersihand
048: */
049: public class SpeedoSequenceManager implements SequenceManager,
050: BindingController {
051:
052: public final static String PMF_BINDING = "po-manager-factory";
053: public final static String MAPPER_BINDING = "mapper";
054: public final static String MAPPER_RDB_BINDING = "mapper-rdb";
055:
056: /**
057: * JORM object encapsulating the datastore
058: */
059: private PMapper mapper = null;
060:
061: /**
062: * JORM object encapsulating the datastore but in rdb version (optional)
063: */
064: private PMapperRdb mapperRdb = null;
065:
066: /**
067: * The PMF
068: */
069: private POManagerFactoryItf pmf = null;
070:
071: /**
072: * Manages the log's traces
073: */
074: private Logger logger = null;
075:
076: public Logger getLogger() {
077: return logger;
078: }
079:
080: public void setLogger(Logger logger) {
081: this .logger = logger;
082: }
083:
084: public PMapper getMapper() {
085: return mapper;
086: }
087:
088: public void setMapper(PMapper mapper) {
089: this .mapper = mapper;
090: }
091:
092: public PMapperRdb getMapperRdb() {
093: return mapperRdb;
094: }
095:
096: public void setMapperRdb(PMapperRdb mapperRdb) {
097: this .mapperRdb = mapperRdb;
098: }
099:
100: // IMPLEMENTATION OF THE UserBindingController INTERFACE //
101: //-------------------------------------------------------//
102:
103: public String[] listFc() {
104: return new String[] { PMF_BINDING, MAPPER_BINDING,
105: MAPPER_RDB_BINDING };
106: }
107:
108: public Object lookupFc(String s) {
109: if (PMF_BINDING.equals(s)) {
110: return pmf;
111: } else if (MAPPER_BINDING.equals(s)) {
112: return mapper;
113: } else if (MAPPER_RDB_BINDING.equals(s)) {
114: return mapperRdb;
115: } else
116: return null;
117: }
118:
119: public void bindFc(String s, Object o) {
120: if ("logger".equals(s)) {
121: logger = (Logger) o;
122: } else if (PMF_BINDING.equals(s)) {
123: pmf = (POManagerFactoryItf) o;
124: } else if (MAPPER_BINDING.equals(s)) {
125: mapper = (PMapper) o;
126: } else if (MAPPER_RDB_BINDING.equals(s)) {
127: mapperRdb = (PMapperRdb) o;
128: }
129: }
130:
131: public void unbindFc(String s) {
132: if (PMF_BINDING.equals(s)) {
133: pmf = null;
134: } else if (MAPPER_BINDING.equals(s)) {
135: mapper = null;
136: } else if (MAPPER_RDB_BINDING.equals(s)) {
137: mapperRdb = null;
138: }
139: }
140:
141: // IMPLEMENTATION OF THE SequenceManager INTERFACE //
142: //--------------------------------------------------//
143:
144: /**
145: * Map of sequences defined for the pmf.
146: * The Map key is the fully qualified sequence name,
147: * i.e "packageName.sequenceName".
148: */
149: private Map sequenceName2sequences = new HashMap();
150:
151: /**
152: * The long generator manager
153: */
154: private Object longGenMgr = null;
155:
156: /**
157: * Get the long generator manager.
158: */
159: public Object getLongGenMgr() {
160: return longGenMgr;
161: }
162:
163: /**
164: * Set the long generator manager.
165: */
166: public void setLongGenMgr(Object longGenMgr) {
167: if (longGenMgr instanceof LongGenMgr) {
168: this .longGenMgr = longGenMgr;
169: }
170: }
171:
172: /**
173: * Add the sequence if not already registered in the list.
174: * The key is the fully qualified name of the sequence,
175: * i.e "packageName.sequenceName".
176: * @param sequence
177: */
178: public void addSequence(Object sequence) {
179: if (sequence instanceof SpeedoSequence) {
180: SpeedoSequence s = (SpeedoSequence) sequence;
181: String fqName = (s.packageName == null) ? ("")
182: : (s.packageName + ".") + s.name;
183: //if the sequence is not already registered
184: if (!sequenceName2sequences.containsKey(fqName)) {
185: sequenceName2sequences.put(fqName, s);
186: s.setSequenceManager(this );
187: }
188: }
189: }
190:
191: /**
192: * Try to remove the sequence identified by the sequenceName.
193: * If the sequence does not exist, nothing is done.
194: * @param sequenceName the fully qualified name of the sequence,
195: * i.e "packageName.sequenceName".
196: */
197: public void removeSequence(String sequenceName) {
198: sequenceName2sequences.remove(sequenceName);
199: }
200:
201: /**
202: * Return the sequence associated to the name parameter.
203: * If no sequence is found, return null.
204: * @param name the fully qualified name of the sequence,
205: * i.e "packageName.sequenceName".
206: */
207: public SpeedoSequenceItf getSequence(String name) {
208: SpeedoSequence s = (SpeedoSequence) sequenceName2sequences
209: .get(name);
210: if (s != null) {
211: try {
212: initSequence(s);
213: } catch (Exception e) {
214: logger.log(BasicLevel.ERROR,
215: "Impossible to get the sequence " + name,
216: ExceptionHelper.getNested(e));
217: return null;
218: }
219: }
220: return s;
221: }
222:
223: public POManagerFactoryItf getPMF() {
224: return pmf;
225: }
226:
227: public void setPMF(POManagerFactoryItf pmf) {
228: this .pmf = pmf;
229: }
230:
231: /**
232: * Assuming this sequence is registered,
233: * init the sequence:
234: * - on the datastore if the sequence has a datastore name
235: * - in memory if the sequence has no datastore name
236: * If the sequence does not exist, do nothing.
237: * @throws PException
238: */
239: private void initSequence(Object sequence) throws PException {
240: if (sequence instanceof SpeedoSequence) {
241: try {
242: SpeedoSequence s = (SpeedoSequence) sequence;
243: //if the sequence is not a rdb sequence, use jf_longGen table
244: if (s.datastoreName == null
245: || s.datastoreName.equals("")) {
246: if (longGenMgr == null) {
247: //try to find the long gen manager in the registry
248: synchronized (LongGenMgrRegistry.class) {
249: longGenMgr = LongGenMgrRegistry
250: .getLongGenMgr(mapper);
251: if (longGenMgr == null) {
252: //if not already registered, create it
253: try {
254: longGenMgr = (LongGenMgr) Class
255: .forName(
256: getLongGenMgrName())
257: .newInstance();
258: } catch (Exception e) {
259: throw new PException(
260: e,
261: "Cannot create LongGenMgr (probably a ClassLoader problem): "
262: + getLongGenMgrName());
263: }
264: ((LongGenMgr) longGenMgr)
265: .init(
266: mapper,
267: PClassMapping.CREATE_STRUCTURE_IF_NEEDED);
268: // and register it
269: LongGenMgrRegistry
270: .registerLonGenMgr((LongGenMgr) longGenMgr);
271: }
272: }
273: }
274: //create the long gen and associate it to the sequence
275: s.setLongGen(((LongGenMgr) longGenMgr).getLongGen(s
276: .getName()));
277: } else {
278: //else, use rdb_sequence_long_gen
279: if (mapperRdb != null) {
280: if (s.getLongGen() == null) {
281: RdbSequenceLongGen rdbLongGen = new RdbSequenceLongGen(
282: mapperRdb, s.datastoreName, false);
283: if (s.start != null) {
284: rdbLongGen.setSequenceStart(s.start);
285: }
286: if (s.increment != null) {
287: rdbLongGen
288: .setSequenceIncrement(s.increment);
289: }
290: if (s.cache != null) {
291: rdbLongGen.setSequenceStart(s.cache);
292: }
293: //create it
294: Object conn = mapperRdb.getConnection();
295: rdbLongGen.createSequence(conn);
296: //and associate it to the sequence
297: s.setLongGen(rdbLongGen);
298: //close the connection
299: mapperRdb.closeConnection(conn);
300: }
301: } else {
302: throw new PException(
303: "Problem while init the sequence "
304: + ((SpeedoSequence) sequence)
305: .getName()
306: + ": "
307: + "a rdb sequence has been defined in a jdo file and no rdb is linked to the application.");
308: }
309: }
310: } catch (Exception e) {
311: throw new PException(e,
312: "Problem while init the sequence "
313: + ((SpeedoSequence) sequence).getName());
314: }
315: }
316: }
317:
318: /**
319: * Calculates the class name of the LongGenMgr from the mapper name. Indeed
320: * the class is the generated PClassMapping of the persistent class
321: * org.objectweb.jorm.facility.naming.generator.LongGenIncr.
322: */
323: private String getLongGenMgrName() {
324: String mn = mapper.getMapperName();
325: int idx = mn.indexOf('.');
326: if (idx != -1) {
327: mn = mn.substring(0, idx);
328: }
329: return "org.objectweb.jorm.facility.naming.generator." + mn
330: + ".LongGenIncrMapping";
331: }
332: }
|