001: /*
002:
003: Derby - Class org.apache.derby.impl.services.monitor.StorageFactoryService
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.services.monitor;
023:
024: import org.apache.derby.iapi.reference.MessageId;
025: import org.apache.derby.iapi.reference.SQLState;
026:
027: import org.apache.derby.iapi.services.i18n.MessageService;
028:
029: import org.apache.derby.iapi.services.monitor.Monitor;
030: import org.apache.derby.iapi.services.monitor.PersistentService;
031: import org.apache.derby.iapi.services.sanity.SanityManager;
032:
033: import org.apache.derby.iapi.error.StandardException;
034: import org.apache.derby.iapi.store.raw.data.DataFactory;
035:
036: import org.apache.derby.io.StorageFile;
037: import org.apache.derby.io.StorageFactory;
038: import org.apache.derby.io.WritableStorageFactory;
039:
040: import org.apache.derby.iapi.reference.Attribute;
041: import org.apache.derby.iapi.reference.Property;
042:
043: import java.io.File;
044: import java.io.FileInputStream;
045: import java.io.FileOutputStream;
046: import java.io.InputStream;
047: import java.io.BufferedInputStream;
048: import java.io.OutputStream;
049: import java.io.IOException;
050: import java.io.FileNotFoundException;
051:
052: import java.util.Enumeration;
053: import java.util.NoSuchElementException;
054: import java.util.Properties;
055:
056: import java.security.AccessController;
057: import java.security.PrivilegedAction;
058: import java.security.PrivilegedExceptionAction;
059: import java.security.PrivilegedActionException;
060:
061: /**
062: * This class implements the PersistentService interface using a StorageFactory class.
063: * It handles all subSubProtocols except for cache.
064: */
065: final class StorageFactoryService implements PersistentService {
066:
067: private String home; // the path of the database home directory. Can be null
068: private String canonicalHome; // will be null if home is null
069: private final String subSubProtocol;
070: private final Class storageFactoryClass;
071: private StorageFactory rootStorageFactory;
072: private char separatorChar;
073:
074: StorageFactoryService(String subSubProtocol,
075: Class storageFactoryClass) throws StandardException {
076: this .subSubProtocol = subSubProtocol;
077: this .storageFactoryClass = storageFactoryClass;
078:
079: Object monitorEnv = Monitor.getMonitor().getEnvironment();
080: if (monitorEnv instanceof File) {
081: final File relativeRoot = (File) monitorEnv;
082: try {
083: AccessController
084: .doPrivileged(new java.security.PrivilegedExceptionAction() {
085: public Object run() throws IOException,
086: StandardException {
087: home = relativeRoot.getPath();
088: canonicalHome = relativeRoot
089: .getCanonicalPath();
090: rootStorageFactory = getStorageFactoryInstance(
091: true, null, null, null);
092: if (home != null) {
093: StorageFile rootDir = rootStorageFactory
094: .newStorageFile(null);
095: rootDir.mkdirs();
096: }
097: return null;
098: }
099: });
100: } catch (PrivilegedActionException pae) {
101: home = null;
102: canonicalHome = null;
103: }
104: }
105: if (rootStorageFactory == null) {
106: try {
107: rootStorageFactory = getStorageFactoryInstance(true,
108: null, null, null);
109: } catch (IOException ioe) {
110: throw Monitor
111: .exceptionStartingModule(/*serviceName, */ioe);
112: }
113: }
114: AccessController
115: .doPrivileged(new java.security.PrivilegedAction() {
116: public Object run() {
117: separatorChar = rootStorageFactory
118: .getSeparator();
119: return null;
120: }
121: });
122: } // end of constructor
123:
124: /*
125: ** Methods of PersistentService
126: */
127:
128: /**
129: * @return true if the PersistentService has a StorageFactory, false if not.
130: */
131: public boolean hasStorageFactory() {
132: return true;
133: }
134:
135: /**
136: * Get an initialized StorageFactoryInstance
137: *
138: * @param useHome If true and the database name is not absolute then the database directory will be
139: * relative to the home directory, if one is defined in the properties file.
140: * @param databaseName The name of the database (directory). The name does not include the subSubProtocol.
141: * If null then the storage factory will only be used to deal with the directory containing
142: * the databases.
143: * @param tempDirName The name of the temporary file directory set in properties. If null then a default
144: * directory should be used. Each database should get a separate temporary file
145: * directory within this one to avoid collisions.
146: * @param uniqueName A unique name that can be used to create the temporary file directory for this database.
147: * If null then temporary files will not be created in this StorageFactory instance.
148: *
149: * @return An initialized StorageFactory.
150: *
151: * @exception IOException if create, the database directory does not exist, and it cannot be created;
152: * if !create and the database does not exist as a directory.
153: */
154: public StorageFactory getStorageFactoryInstance(
155: final boolean useHome, final String databaseName,
156: final String tempDirName, final String uniqueName)
157: throws StandardException, IOException {
158: try {
159: return (StorageFactory) AccessController
160: .doPrivileged(new PrivilegedExceptionAction() {
161: public Object run()
162: throws InstantiationException,
163: IllegalAccessException, IOException {
164: return privGetStorageFactoryInstance(
165: useHome, databaseName, tempDirName,
166: uniqueName);
167: }
168: });
169: } catch (PrivilegedActionException pae) {
170: Exception e = pae.getException();
171: throw StandardException.newException(
172: SQLState.REGISTERED_CLASS_INSTANCE_ERROR, e,
173: subSubProtocol, storageFactoryClass);
174: }
175: } // end of getStorageFactoryInstance
176:
177: private StorageFactory privGetStorageFactoryInstance(
178: boolean useHome, String databaseName, String tempDirName,
179: String uniqueName) throws InstantiationException,
180: IllegalAccessException, IOException {
181: StorageFactory storageFactory = (StorageFactory) storageFactoryClass
182: .newInstance();
183: String dbn;
184: if (databaseName != null && subSubProtocol != null
185: && databaseName.startsWith(subSubProtocol + ":"))
186: dbn = databaseName.substring(subSubProtocol.length() + 1);
187: else
188: dbn = databaseName;
189: storageFactory.init(useHome ? home : null, dbn, tempDirName,
190: uniqueName);
191: return storageFactory;
192: } // end of privGetStorageFactoryInstance
193:
194: /**
195: The type of the service is 'directory'
196:
197: @see PersistentService#getType
198: */
199: public String getType() {
200: return subSubProtocol;
201: }
202:
203: /**
204: Return a list of all the directoies in the system directory.
205:
206: @see PersistentService#getBootTimeServices
207: */
208: public Enumeration getBootTimeServices() {
209: if (home == null)
210: return null;
211: return new DirectoryList();
212: }
213:
214: /**
215: Open the service properties in the directory identified by the service name.
216:
217: The property SERVICE_ROOT (db2j.rt.serviceRoot) is added
218: by this method and set to the service directory.
219:
220: @return A Properties object or null if serviceName does not represent a valid service.
221:
222: @exception StandardException Service appears valid but the properties cannot be created.
223: */
224: public Properties getServiceProperties(final String serviceName,
225: Properties defaultProperties) throws StandardException {
226: if (SanityManager.DEBUG) {
227: if (!serviceName
228: .equals(getCanonicalServiceName(serviceName))) {
229: SanityManager
230: .THROWASSERT("serviceName ("
231: + serviceName
232: + ") expected to equal getCanonicalServiceName(serviceName) ("
233: + getCanonicalServiceName(serviceName)
234: + ")");
235: }
236: }
237:
238: //recreate the service root if requested by the user.
239: final String recreateFrom = recreateServiceRoot(serviceName,
240: defaultProperties);
241:
242: InputStream is = null;
243: try {
244: is = (InputStream) AccessController
245: .doPrivileged(new PrivilegedExceptionAction() {
246: public Object run()
247: throws FileNotFoundException,
248: IOException, StandardException,
249: InstantiationException,
250: IllegalAccessException {
251: if (recreateFrom != null) // restore from a file
252: {
253: File propFile = new File(
254: recreateFrom,
255: PersistentService.PROPERTIES_NAME);
256: return new FileInputStream(propFile);
257: } else {
258: StorageFactory storageFactory = privGetStorageFactoryInstance(
259: true, serviceName, null, null);
260: StorageFile file = storageFactory
261: .newStorageFile(PersistentService.PROPERTIES_NAME);
262: InputStream is1 = file.getInputStream();
263: storageFactory.shutdown();
264: return is1;
265: }
266: }
267: });
268:
269: Properties serviceProperties = new Properties(
270: defaultProperties);
271: serviceProperties.load(new BufferedInputStream(is));
272:
273: return serviceProperties;
274: } catch (PrivilegedActionException pae) {
275: if (pae.getException() instanceof FileNotFoundException)
276: return null;
277: throw Monitor.exceptionStartingModule(pae.getException());
278: } catch (FileNotFoundException fnfe) {
279: return null;
280: } catch (SecurityException se) {
281: throw Monitor.exceptionStartingModule(/*serviceName, */se);
282: } catch (IOException ioe) {
283: throw Monitor
284: .exceptionStartingModule(/*serviceName, */ioe);
285: } finally {
286: if (is != null) {
287: try {
288: is.close();
289: } catch (IOException ioe2) {
290: }
291: }
292: }
293: } // end of getServiceProperties
294:
295: /**
296: @exception StandardException Properties cannot be saved.
297: */
298:
299: public void saveServiceProperties(final String serviceName,
300: StorageFactory sf, final Properties properties,
301: final boolean replace) throws StandardException {
302: if (SanityManager.DEBUG) {
303: SanityManager.ASSERT(serviceName
304: .equals(getCanonicalServiceName(serviceName)),
305: serviceName);
306: }
307: if (!(sf instanceof WritableStorageFactory))
308: throw StandardException
309: .newException(SQLState.READ_ONLY_SERVICE);
310: final WritableStorageFactory storageFactory = (WritableStorageFactory) sf;
311: try {
312: AccessController
313: .doPrivileged(new PrivilegedExceptionAction() {
314: public Object run() throws StandardException {
315: StorageFile backupFile = null;
316: StorageFile servicePropertiesFile = storageFactory
317: .newStorageFile(PersistentService.PROPERTIES_NAME);
318:
319: if (replace) {
320: backupFile = storageFactory
321: .newStorageFile(PersistentService.PROPERTIES_NAME
322: .concat("old"));
323: try {
324: if (!servicePropertiesFile
325: .renameTo(backupFile))
326: throw StandardException
327: .newException(
328: SQLState.UNABLE_TO_RENAME_FILE,
329: servicePropertiesFile,
330: backupFile);
331: } catch (SecurityException se) {
332: throw Monitor
333: .exceptionStartingModule(se);
334: }
335: }
336:
337: OutputStream os = null;
338: try {
339: os = servicePropertiesFile
340: .getOutputStream();
341: properties
342: .store(
343: os,
344: serviceName
345: + MessageService
346: .getTextMessage(MessageId.SERVICE_PROPERTIES_DONT_EDIT));
347: storageFactory.sync(os, false);
348: os.close();
349: os = null;
350: } catch (IOException ioe) {
351: if (os != null) {
352: try {
353: os.close();
354: } catch (IOException ioe2) {
355: }
356: os = null;
357: }
358:
359: if (backupFile != null) {
360: // need to re-name the old properties file back again
361: try {
362: servicePropertiesFile.delete();
363: backupFile
364: .renameTo(servicePropertiesFile);
365: } catch (SecurityException se) {
366: }
367: }
368: throw Monitor
369: .exceptionStartingModule(ioe);
370: }
371:
372: if (backupFile != null) {
373: try {
374: backupFile.delete();
375: backupFile = null;
376: } catch (SecurityException se) {
377: }
378: }
379: return null;
380: }
381: });
382: } catch (PrivilegedActionException pae) {
383: throw (StandardException) pae.getException();
384: }
385: } // end of saveServiceProperties
386:
387: /**
388: Save to a backup file
389:
390: @exception StandardException Properties cannot be saved.
391: */
392:
393: public void saveServiceProperties(final String serviceName,
394: final Properties properties, final boolean replace)
395: throws StandardException {
396:
397: try {
398: AccessController
399: .doPrivileged(new PrivilegedExceptionAction() {
400: File backupFile = null;
401:
402: public Object run() throws StandardException {
403:
404: File servicePropertiesFile = new File(
405: serviceName,
406: PersistentService.PROPERTIES_NAME);
407: if (replace) {
408: backupFile = new File(
409: serviceName,
410: PersistentService.PROPERTIES_NAME
411: .concat("old"));
412: try {
413: if (!servicePropertiesFile
414: .renameTo(backupFile)) {
415: throw StandardException
416: .newException(
417: SQLState.UNABLE_TO_RENAME_FILE,
418: servicePropertiesFile,
419: backupFile);
420: }
421: } catch (SecurityException se) {
422: throw Monitor
423: .exceptionStartingModule(se);
424: }
425: }
426:
427: FileOutputStream fos = null;
428: try {
429:
430: fos = new FileOutputStream(
431: servicePropertiesFile);
432: properties
433: .store(
434: fos,
435: serviceName
436: + MessageService
437: .getTextMessage(MessageId.SERVICE_PROPERTIES_DONT_EDIT));
438: fos.getFD().sync();
439: fos.close();
440: fos = null;
441: } catch (IOException ioe) {
442:
443: if (fos != null) {
444: try {
445: fos.close();
446: } catch (IOException ioe2) {
447: }
448: fos = null;
449: }
450:
451: if (backupFile != null) {
452: // need to re-name the old properties file back again
453: try {
454: servicePropertiesFile.delete();
455: backupFile
456: .renameTo(servicePropertiesFile);
457: } catch (SecurityException se) {
458: }
459: }
460: throw Monitor
461: .exceptionStartingModule(ioe);
462: }
463:
464: if (backupFile != null) {
465: try {
466: backupFile.delete();
467: backupFile = null;
468: } catch (SecurityException se) {
469: // do nothing
470: }
471: }
472: return null;
473: }
474: });
475: } catch (PrivilegedActionException pae) {
476: throw (StandardException) pae.getException();
477: }
478: }
479:
480: /*
481: **Recreates service root if required depending on which of the following
482: **attribute is specified on the conection URL:
483: ** Attribute.CREATE_FROM (Create database from backup if it does not exist):
484: ** When a database not exist, the service(database) root is created
485: ** and the PersistentService.PROPERTIES_NAME (service.properties) file
486: ** is restored from the backup.
487: ** Attribute.RESTORE_FROM (Delete the whole database if it exists and then restore
488: ** it from backup)
489: ** Existing database root is deleted and the new the service(database) root is created.
490: ** PersistentService.PROPERTIES_NAME (service.properties) file is restored from the backup.
491: ** Attribute.ROLL_FORWARD_RECOVERY_FROM:(Perform Rollforward Recovery;
492: ** except for the log directory everthing else is replced by the copy from
493: ** backup. log files in the backup are copied to the existing online log
494: ** directory.):
495: ** When a database not exist, the service(database) root is created.
496: ** PersistentService.PROPERTIES_NAME (service.properties) file is deleted
497: ** from the service dir and recreated with the properties from backup.
498: */
499:
500: protected String recreateServiceRoot(final String serviceName,
501: Properties properties) throws StandardException {
502: //if there are no propertues then nothing to do in this routine
503: if (properties == null) {
504: return null;
505: }
506:
507: String restoreFrom; //location where backup copy of service properties available
508: boolean createRoot = false;
509: boolean deleteExistingRoot = false;
510:
511: //check if user wants to create a database from a backup copy
512: restoreFrom = properties.getProperty(Attribute.CREATE_FROM);
513: if (restoreFrom != null) {
514: //create root dicretory if it does not exist.
515: createRoot = true;
516: deleteExistingRoot = false;
517: } else { //check if user requested a complete restore(version recovery) from backup
518: restoreFrom = properties
519: .getProperty(Attribute.RESTORE_FROM);
520: //create root dir if it does not exists and if there exists one already delete and recreate
521: if (restoreFrom != null) {
522: createRoot = true;
523: deleteExistingRoot = true;
524: } else {
525: //check if user has requested roll forward recovery using a backup
526: restoreFrom = properties
527: .getProperty(Attribute.ROLL_FORWARD_RECOVERY_FROM);
528: if (restoreFrom != null) {
529: //if service root does not exist then only create one
530: //This is useful when logDevice was on some other device
531: //and the device on which data directorties existied has
532: //failed and user is trying to restore it some other device.
533: try {
534: if (AccessController
535: .doPrivileged(new PrivilegedExceptionAction() {
536: public Object run()
537: throws IOException,
538: StandardException,
539: InstantiationException,
540: IllegalAccessException {
541: StorageFactory storageFactory = privGetStorageFactoryInstance(
542: true, serviceName,
543: null, null);
544: try {
545: StorageFile serviceDirectory = storageFactory
546: .newStorageFile(null);
547: return serviceDirectory
548: .exists() ? this
549: : null;
550: } finally {
551: storageFactory.shutdown();
552: }
553: }
554: }) == null) {
555: createRoot = true;
556: deleteExistingRoot = false;
557: }
558:
559: } catch (PrivilegedActionException pae) {
560: throw Monitor
561: .exceptionStartingModule((IOException) pae
562: .getException());
563: }
564: }
565: }
566: }
567:
568: //restore the service properties from backup
569: if (restoreFrom != null) {
570: //First make sure backup service directory exists in the specified path
571: File backupRoot = new File(restoreFrom);
572: if (backupRoot.exists()) {
573: //First make sure backup have service.properties
574: File bserviceProp = new File(restoreFrom,
575: PersistentService.PROPERTIES_NAME);
576: if (bserviceProp.exists()) {
577: //create service root if required
578: if (createRoot)
579: createServiceRoot(serviceName,
580: deleteExistingRoot);
581: try {
582: AccessController
583: .doPrivileged(new PrivilegedExceptionAction() {
584: public Object run()
585: throws IOException,
586: StandardException,
587: InstantiationException,
588: IllegalAccessException {
589: WritableStorageFactory storageFactory = (WritableStorageFactory) privGetStorageFactoryInstance(
590: true, serviceName,
591: null, null);
592: try {
593: StorageFile cserviceProp = storageFactory
594: .newStorageFile(PersistentService.PROPERTIES_NAME);
595:
596: if (cserviceProp.exists())
597: if (!cserviceProp
598: .delete())
599: throw StandardException
600: .newException(
601: SQLState.UNABLE_TO_DELETE_FILE,
602: cserviceProp);
603: return null;
604: } finally {
605: storageFactory.shutdown();
606: }
607: }
608: });
609: } catch (PrivilegedActionException pae) {
610: throw Monitor
611: .exceptionStartingModule((IOException) pae
612: .getException());
613: }
614: } else
615: throw StandardException.newException(
616: SQLState.PROPERTY_FILE_NOT_FOUND_IN_BACKUP,
617: bserviceProp);
618: } else
619: throw StandardException.newException(
620: SQLState.SERVICE_DIRECTORY_NOT_IN_BACKUP,
621: backupRoot);
622:
623: properties.put(Property.IN_RESTORE_FROM_BACKUP, "True");
624: if (createRoot)
625: properties.put(Property.DELETE_ROOT_ON_ERROR, "True");
626: }
627: return restoreFrom;
628: } // end of recreateServiceRoot
629:
630: /**
631: Properties cannot be saved
632: */
633: public String createServiceRoot(final String name,
634: final boolean deleteExisting) throws StandardException {
635: if (!(rootStorageFactory instanceof WritableStorageFactory))
636: throw StandardException
637: .newException(SQLState.READ_ONLY_SERVICE);
638: // we need to create the directory before we can call
639: // getCanonicalPath() on it, because if intermediate directories
640: // need to be created the getCanonicalPath() will fail.
641:
642: Throwable t = null;
643: try {
644: String protocolLeadIn = "";
645: //prepend the subsub protocol name to the storage factoty canonical
646: //name to form the service name except in case of the the
647: //default subsubprototcol(PersistentService.DIRECTORY)
648:
649: if (!(getType().equals(PersistentService.DIRECTORY)))
650: protocolLeadIn = getType() + ":";
651:
652: return protocolLeadIn
653: + (String) AccessController
654: .doPrivileged(new PrivilegedExceptionAction() {
655: public Object run()
656: throws StandardException,
657: IOException,
658: InstantiationException,
659: IllegalAccessException {
660: StorageFactory storageFactory = privGetStorageFactoryInstance(
661: true, name, null, null);
662: try {
663: StorageFile serviceDirectory = storageFactory
664: .newStorageFile(null);
665:
666: if (serviceDirectory.exists()) {
667: if (deleteExisting) {
668: if (!serviceDirectory
669: .deleteAll())
670: throw StandardException
671: .newException(
672: SQLState.SERVICE_DIRECTORY_REMOVE_ERROR,
673: getDirectoryPath(name));
674: } else
675: throw StandardException
676: .newException(
677: SQLState.SERVICE_DIRECTORY_EXISTS_ERROR,
678: getDirectoryPath(name));
679: }
680:
681: if (serviceDirectory.mkdirs()) {
682: try {
683: return storageFactory
684: .getCanonicalName();
685: } catch (IOException ioe) {
686: serviceDirectory
687: .deleteAll();
688: throw ioe;
689: }
690: }
691: throw StandardException
692: .newException(
693: SQLState.SERVICE_DIRECTORY_CREATE_ERROR,
694: serviceDirectory);
695: } finally {
696: storageFactory.shutdown();
697: }
698: }
699: });
700: } catch (SecurityException se) {
701: t = se;
702: } catch (PrivilegedActionException pae) {
703: t = pae.getException();
704: if (t instanceof StandardException)
705: throw (StandardException) t;
706: }
707:
708: throw StandardException.newException(
709: SQLState.SERVICE_DIRECTORY_CREATE_ERROR, t, name);
710: } // end of createServiceRoot
711:
712: private String getDirectoryPath(String name) {
713: StringBuffer sb = new StringBuffer();
714: if (home != null) {
715: sb.append(home);
716: sb.append(separatorChar);
717: }
718: if (separatorChar != '/')
719: sb.append(name.replace('/', separatorChar));
720: else
721: sb.append(name);
722: return sb.toString();
723: } // end of getDirectoryPath
724:
725: public boolean removeServiceRoot(final String serviceName) {
726: if (!(rootStorageFactory instanceof WritableStorageFactory))
727: return false;
728: try {
729: return AccessController
730: .doPrivileged(new PrivilegedExceptionAction() {
731: public Object run() throws StandardException,
732: IOException, InstantiationException,
733: IllegalAccessException {
734: StorageFactory storageFactory = privGetStorageFactoryInstance(
735: true, serviceName, null, null);
736: try {
737: if (SanityManager.DEBUG)
738: SanityManager
739: .ASSERT(
740: serviceName
741: .equals(storageFactory
742: .getCanonicalName()),
743: serviceName);
744: StorageFile serviceDirectory = storageFactory
745: .newStorageFile(null);
746: return serviceDirectory.deleteAll() ? this
747: : null;
748: } finally {
749: storageFactory.shutdown();
750: }
751: }
752: }) != null;
753: } catch (PrivilegedActionException pae) {
754: return false;
755: }
756: } // end of removeServiceRoot
757:
758: public String getCanonicalServiceName(String name)
759: throws StandardException {
760: String protocolLeadIn = getType() + ":";
761: int colon = name.indexOf(':');
762: if (colon > 1) // Subsubprotocols must be at least 2 characters long
763: {
764: if (!name.startsWith(protocolLeadIn))
765: return null; // It is not our database
766: name = name.substring(colon + 1);
767: }
768: if (getType().equals(PersistentService.DIRECTORY)) // The default subsubprototcol
769: protocolLeadIn = "";
770: final String nm = name;
771:
772: try {
773: return protocolLeadIn
774: + (String) AccessController
775: .doPrivileged(new PrivilegedExceptionAction() {
776: public Object run()
777: throws StandardException,
778: IOException,
779: InstantiationException,
780: IllegalAccessException {
781: StorageFactory storageFactory = privGetStorageFactoryInstance(
782: true, nm, null, null);
783: try {
784: return storageFactory
785: .getCanonicalName();
786: } finally {
787: storageFactory.shutdown();
788: }
789: }
790: });
791: } catch (PrivilegedActionException pae) {
792: throw Monitor.exceptionStartingModule(pae.getException());
793: }
794: } // end of getCanonicalServiceName
795:
796: public String getUserServiceName(String serviceName) {
797: if (home != null) {
798: // allow for file separatorChar by adding 1 to the length
799: if ((serviceName.length() > (canonicalHome.length() + 1))
800: && serviceName.startsWith(canonicalHome)) {
801: serviceName = serviceName.substring(canonicalHome
802: .length());
803: if (serviceName.charAt(0) == separatorChar)
804: serviceName = serviceName.substring(1);
805: }
806: }
807:
808: return serviceName.replace(separatorChar, '/');
809: }
810:
811: public boolean isSameService(String serviceName1,
812: String serviceName2) {
813: if (SanityManager.DEBUG) {
814: try {
815: SanityManager.ASSERT(serviceName1
816: .equals(getCanonicalServiceName(serviceName1)),
817: serviceName1);
818: SanityManager.ASSERT(serviceName2
819: .equals(getCanonicalServiceName(serviceName2)),
820: serviceName2);
821: } catch (StandardException se) {
822: return false;
823: }
824: }
825: return serviceName1.equals(serviceName2);
826: } // end of isSameService
827:
828: /**
829: * Get the StorageFactory implementation for this PersistentService
830: *
831: * @return the StorageFactory class.
832: */
833: public Class getStorageFactoryClass() {
834: return storageFactoryClass;
835: }
836:
837: final class DirectoryList implements Enumeration, PrivilegedAction {
838: private String[] contents;
839: private StorageFile systemDirectory;
840:
841: private int index;
842: private boolean validIndex;
843:
844: private int actionCode;
845: private static final int INIT_ACTION = 0;
846: private static final int HAS_MORE_ELEMENTS_ACTION = 1;
847:
848: DirectoryList() {
849: actionCode = INIT_ACTION;
850: AccessController.doPrivileged(this );
851: }
852:
853: public boolean hasMoreElements() {
854: if (validIndex)
855: return true;
856:
857: actionCode = HAS_MORE_ELEMENTS_ACTION;
858: return AccessController.doPrivileged(this ) != null;
859: } // end of hasMoreElements
860:
861: public Object nextElement() throws NoSuchElementException {
862: if (!hasMoreElements())
863: throw new NoSuchElementException();
864:
865: validIndex = false;
866: return contents[index++];
867: } // end of nextElement
868:
869: // PrivilegedAction method
870: public final Object run() {
871: switch (actionCode) {
872: case INIT_ACTION:
873: systemDirectory = rootStorageFactory
874: .newStorageFile(null);
875: contents = systemDirectory.list();
876: return null;
877:
878: case HAS_MORE_ELEMENTS_ACTION:
879: for (; index < contents.length; contents[index++] = null) {
880: try {
881: StorageFactory storageFactory = privGetStorageFactoryInstance(
882: true, contents[index], null, null);
883: try {
884: StorageFile properties = storageFactory
885: .newStorageFile(PersistentService.PROPERTIES_NAME);
886: if (!properties.exists())
887: continue;
888: // convert to a canonical name while we are here.
889: contents[index] = storageFactory
890: .getCanonicalName();
891: validIndex = true;
892:
893: return this ;
894: } finally {
895: storageFactory.shutdown();
896: }
897: } catch (Exception se) {
898: continue;
899: }
900: }
901: return null;
902: }
903: return null;
904: } // end of run
905: } // end of class DirectoryList
906: }
|