001: ///////////////////////////////////////////////////////////////////////////////
002: //
003: // Copyright (C) 2003-@year@ by Thomas M. Hazel, MyOODB (www.myoodb.org)
004: //
005: // All Rights Reserved
006: //
007: // This program is free software; you can redistribute it and/or modify
008: // it under the terms of the GNU General Public License and GNU Library
009: // General Public License as published by the Free Software Foundation;
010: // either version 2, or (at your option) any later version.
011: //
012: // This program is distributed in the hope that it will be useful,
013: // but WITHOUT ANY WARRANTY; without even the implied warranty of
014: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: // GNU General Public License and GNU Library General Public License
016: // for more details.
017: //
018: // You should have received a copy of the GNU General Public License
019: // and GNU Library General Public License along with this program; if
020: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
021: // MA 02139, USA.
022: //
023: ///////////////////////////////////////////////////////////////////////////////
024: package org.myoodb.core;
025:
026: import java.io.*;
027: import java.util.*;
028: import java.lang.reflect.Method;
029: import java.lang.reflect.Constructor;
030:
031: import org.myoodb.*;
032: import org.myoodb.exception.*;
033:
034: public final class MyOodbManager {
035: private static final org.myoodb.util.Logger LOGGER = org.myoodb.util.Logger
036: .getLogger(MyOodbManager.class);
037:
038: public volatile static String ROOT_DIR = "roots";
039: public volatile static String OBJECT_DIR = "objs";
040:
041: public final static String VERSION = "@version@";
042: public final static String ID_FILE = "id.properties";
043: public final static String ID_FILE_TMP = "id.properties.tm";
044: public final static String USER_FILE = "user.properties";
045: public final static String USER_FILE_TMP = "user.properties.tm";
046:
047: public final static int SERVER_THREAD_PRIORITY = Thread.NORM_PRIORITY + 3;
048: public final static int ACCEPT_THREAD_PRIORITY = Thread.NORM_PRIORITY + 2;
049: public final static int TRANSACTION_THREAD_PRIORITY = Thread.NORM_PRIORITY + 1;
050:
051: private static volatile boolean m_systemExitFlag = true;
052: private static volatile MyOodbManager s_theManager = null;
053: private static volatile String s_storageClassName = "org.myoodb.core.storage.ObjectStore";
054:
055: protected static volatile java.lang.reflect.Method s_loginCallback = null;
056: protected static volatile java.lang.reflect.Method s_logoutCallback = null;
057: protected static volatile java.lang.reflect.Method s_commitObjectCallback = null;
058: protected static volatile java.lang.reflect.Method s_rollbackObjectCallback = null;
059: protected static volatile java.lang.reflect.Method s_preObjectMethodCallback = null;
060: protected static volatile java.lang.reflect.Method s_postObjectMethodCallback = null;
061: protected static volatile java.lang.reflect.Method s_remoteCommandRequestCallback = null;
062:
063: private boolean m_exitingFlag;
064: private boolean m_initializedFlag;
065: private boolean m_shuttingDownFlag;
066:
067: private ArrayList m_managers;
068: private Database m_database;
069: private File m_databaseDirectory;
070: private Properties m_userProperties;
071: private Properties m_identifierProperties;
072:
073: private UserManager m_userManager;
074: private ClassManager m_classManager;
075: private IdentifierManager m_identifierManager;
076: private TransactionManager m_transactionManager;
077:
078: private AbstractStorage m_storeManager;
079: private WorkManager m_workManager;
080: private WorkManager m_sslWorkManager;
081: private TunnelManager m_tunnelManager;
082:
083: public static MyOodbManager getTheManager() {
084: return s_theManager;
085: }
086:
087: public static boolean getTheManagerInitializedFlag() {
088: return (s_theManager != null) ? s_theManager
089: .getInitializedFlag() : false;
090: }
091:
092: public static boolean getTheManagerShuttingdownFlag() {
093: return (s_theManager != null) ? s_theManager
094: .getShuttingdownFlag() : false;
095: }
096:
097: public static void setSystemExitFlag(boolean flag) {
098: m_systemExitFlag = flag;
099: }
100:
101: public static boolean getSystemExitFlag() {
102: return m_systemExitFlag;
103: }
104:
105: public static void setStorageClass(String className) {
106: s_storageClassName = className;
107: }
108:
109: public static String getStorageClass() {
110: return s_storageClassName;
111: }
112:
113: //
114: // method callback signature (org.myoodb.core.DatabaseClient client)
115: //
116: public static void setLoginCallback(Class classType, String method)
117: throws Exception {
118: if (classType != null) {
119: Method[] methods = classType.getMethods();
120: for (int i = 0; i < methods.length; i++) {
121: if (methods[i].getName().equals(method)) {
122: s_loginCallback = methods[i];
123: break;
124: }
125: }
126:
127: if (s_loginCallback == null) {
128: throw new org.myoodb.exception.InternalException(
129: "Did not find method to callback: " + method);
130: }
131: } else {
132: s_loginCallback = null;
133: }
134: }
135:
136: //
137: // method callback signature (org.myoodb.core.DatabaseClient client)
138: //
139: public static void setLogoutCallback(Class classType, String method)
140: throws Exception {
141: if (classType != null) {
142: Method[] methods = classType.getMethods();
143: for (int i = 0; i < methods.length; i++) {
144: if (methods[i].getName().equals(method)) {
145: s_logoutCallback = methods[i];
146: break;
147: }
148: }
149:
150: if (s_logoutCallback == null) {
151: throw new org.myoodb.exception.InternalException(
152: "Did not find method to callback: " + method);
153: }
154: } else {
155: s_logoutCallback = null;
156: }
157: }
158:
159: //
160: // method callback signature (org.myoodb.MyOodbLocal self)
161: //
162: public static void setCommitObjectCallback(Class classType,
163: String method) throws Exception {
164: if (classType != null) {
165: Method[] methods = classType.getMethods();
166: for (int i = 0; i < methods.length; i++) {
167: if (methods[i].getName().equals(method)) {
168: s_commitObjectCallback = methods[i];
169: break;
170: }
171: }
172:
173: if (s_commitObjectCallback == null) {
174: throw new org.myoodb.exception.InternalException(
175: "Did not find method to callback: " + method);
176: }
177: } else {
178: s_commitObjectCallback = null;
179: }
180: }
181:
182: //
183: // method callback signature (org.myoodb.MyOodbLocal self)
184: //
185: public static void setRollbackObjectCallback(Class classType,
186: String method) throws Exception {
187: if (classType != null) {
188: Method[] methods = classType.getMethods();
189: for (int i = 0; i < methods.length; i++) {
190: if (methods[i].getName().equals(method)) {
191: s_rollbackObjectCallback = methods[i];
192: break;
193: }
194: }
195:
196: if (s_rollbackObjectCallback == null) {
197: throw new org.myoodb.exception.InternalException(
198: "Did not find method to callback: " + method);
199: }
200: } else {
201: s_rollbackObjectCallback = null;
202: }
203: }
204:
205: //
206: // method callback signature (org.myoodb.MyOodbLocal self, String methodName, Object[] args)
207: //
208: public static void setPreObjectMethodCallback(Class classType,
209: String method) throws Exception {
210: if (classType != null) {
211: Method[] methods = classType.getMethods();
212: for (int i = 0; i < methods.length; i++) {
213: if (methods[i].getName().equals(method)) {
214: s_preObjectMethodCallback = methods[i];
215: break;
216: }
217: }
218:
219: if (s_preObjectMethodCallback == null) {
220: throw new org.myoodb.exception.InternalException(
221: "Did not find method to callback: " + method);
222: }
223: } else {
224: s_preObjectMethodCallback = null;
225: }
226: }
227:
228: //
229: // method callback signature (org.myoodb.MyOodbLocal self, String methodName, Object[] args)
230: //
231: public static void setPostObjectMethodCallback(Class classType,
232: String method) throws Exception {
233: if (classType != null) {
234: Method[] methods = classType.getMethods();
235: for (int i = 0; i < methods.length; i++) {
236: if (methods[i].getName().equals(method)) {
237: s_postObjectMethodCallback = methods[i];
238: break;
239: }
240: }
241:
242: if (s_postObjectMethodCallback == null) {
243: throw new org.myoodb.exception.InternalException(
244: "Did not find method to callback: " + method);
245: }
246: } else {
247: s_postObjectMethodCallback = null;
248: }
249: }
250:
251: //
252: // method callback signature (org.myoodb.core.command.AbstractCommand command, org.myoodb.core.User user)
253: //
254: public static void setRemoteCommandRequestCallback(Class classType,
255: String method) throws Exception {
256: if (classType != null) {
257: Method[] methods = classType.getMethods();
258: for (int i = 0; i < methods.length; i++) {
259: if (methods[i].getName().equals(method)) {
260: s_remoteCommandRequestCallback = methods[i];
261: break;
262: }
263: }
264:
265: if (s_remoteCommandRequestCallback == null) {
266: throw new org.myoodb.exception.InternalException(
267: "Did not find method to callback: " + method);
268: }
269: } else {
270: s_remoteCommandRequestCallback = null;
271: }
272: }
273:
274: public MyOodbManager(String dirName, boolean storeAsXmlFlag)
275: throws Exception {
276: checkJavaVersion();
277:
278: if (s_theManager != null) {
279: throw new PermissionException(
280: "MyOodbManager already initialized for this JVM");
281: }
282:
283: s_theManager = this ;
284:
285: try {
286: m_databaseDirectory = new File(dirName);
287:
288: if (org.myoodb.core.FileHelper.getMemoryResidentFlag() == false) {
289: if (m_databaseDirectory.isDirectory() == false) {
290: throw new PermissionException(
291: "No database found at '"
292: + m_databaseDirectory + "'.");
293: }
294: }
295:
296: initProperties();
297:
298: if (LOGGER.isInfoEnabled() == true) {
299: LOGGER.info("MyOODB version @version@");
300: LOGGER
301: .info("Copyright (C) 2003-@year@ The MyOODB Project");
302: LOGGER.info("Initializing...");
303: }
304:
305: m_managers = new ArrayList();
306:
307: m_userManager = new UserManager();
308: m_managers.add(m_userManager);
309: m_userManager.startup();
310:
311: m_classManager = new ClassManager();
312: m_managers.add(m_classManager);
313: m_classManager.startup();
314:
315: m_identifierManager = new IdentifierManager();
316: m_managers.add(m_identifierManager);
317: m_identifierManager.startup();
318:
319: m_transactionManager = new TransactionManager();
320: m_managers.add(m_transactionManager);
321: m_transactionManager.startup();
322:
323: /*
324: if (relational database == true)
325: {
326: Class storeClass = m_classManager.getClass(s_storageClassName);
327: if (storeClass == null)
328: {
329: LOGGER.error("Store not found: " + s_storageClassName);
330:
331: if (MyOodbManager.getSystemExitFlag() == true)
332: {
333: System.exit(1);
334: }
335: else
336: {
337: throw new ClassNotFoundException(s_storageClassName);
338: }
339: }
340: Constructor constructor = storeClass.getConstructor(new Class[]{});
341: m_storeManager = (AbstractStorage) constructor.newInstance(new Object[]{});
342: }
343: else
344: */
345: {
346: Class storeClass = m_classManager
347: .getClass(s_storageClassName);
348: if (storeClass == null) {
349: LOGGER.error("Store not found: "
350: + s_storageClassName);
351:
352: if (MyOodbManager.getSystemExitFlag() == true) {
353: System.exit(1);
354: } else {
355: throw new ClassNotFoundException(
356: s_storageClassName);
357: }
358: }
359: Constructor constructor = storeClass
360: .getConstructor(new Class[] {});
361: m_storeManager = (AbstractStorage) constructor
362: .newInstance(new Object[] {});
363: m_storeManager.setStoreAsXmlFlag(storeAsXmlFlag);
364: }
365: m_managers.add(m_storeManager);
366: m_storeManager.startup();
367:
368: m_database = new Database();
369:
370: if (LOGGER.isInfoEnabled() == true) {
371: LOGGER.info("Initialization Complete!");
372: }
373: } catch (Exception e) {
374: s_theManager = null;
375:
376: LOGGER.error("Unable to initialize server: ", e);
377:
378: throw e;
379: }
380: }
381:
382: private void checkJavaVersion() throws Exception {
383: String javaVersion = System.getProperty("java.version");
384: StringTokenizer tokenizer = new StringTokenizer(javaVersion,
385: ".");
386:
387: int majorVersion = 0;
388: if (tokenizer.hasMoreTokens()) {
389: majorVersion = Integer.parseInt(tokenizer.nextToken());
390: }
391: int minorVersion = 0;
392: if (tokenizer.hasMoreTokens()) {
393: minorVersion = Integer.parseInt(tokenizer.nextToken());
394: }
395:
396: if ((majorVersion == 1) && (minorVersion < 5)) {
397: throw new PermissionException(
398: "Java version 1.5 or higher is required to run MyOODB");
399: }
400: }
401:
402: protected void initProperties() throws Exception {
403: m_userProperties = new Properties();
404: m_identifierProperties = new Properties();
405:
406: if (org.myoodb.core.FileHelper.getMemoryResidentFlag() == false) {
407: FileInputStream propIn = new FileInputStream(new File(
408: m_databaseDirectory, USER_FILE));
409:
410: try {
411: m_userProperties.load(propIn);
412: } finally {
413: propIn.close();
414: }
415:
416: propIn = new FileInputStream(new File(m_databaseDirectory,
417: ID_FILE));
418:
419: try {
420: m_identifierProperties.load(propIn);
421: } finally {
422: propIn.close();
423: }
424: } else {
425: m_identifierProperties.setLongProperty(
426: org.myoodb.core.IdentifierManager.XID, 0);
427: }
428: }
429:
430: protected synchronized void storeUserProperties() {
431: if (org.myoodb.core.FileHelper.getMemoryResidentFlag() == false) {
432: org.myoodb.util.FastByteArrayOutputStream baos = new org.myoodb.util.FastByteArrayOutputStream();
433:
434: try {
435: File propFileTemp = new File(m_databaseDirectory,
436: USER_FILE_TMP);
437: OutputStream propOut = new BufferedOutputStream(baos);
438:
439: try {
440: m_userProperties.store(propOut,
441: "User Property File.\n");
442: propOut.flush();
443:
444: RandomAccessFile raFile = new RandomAccessFile(
445: propFileTemp, FileHelper.getFileWriteMode());
446:
447: try {
448: byte[] buffer = baos.toByteArray();
449: raFile.write(buffer, 0, baos.size());
450: } finally {
451: if (raFile != null) {
452: raFile.close();
453: }
454: }
455:
456: File propFile = new File(m_databaseDirectory,
457: USER_FILE);
458: if (propFile.exists()) {
459: FileHelper.delete(propFile);
460: }
461:
462: org.myoodb.core.FileHelper.rename(propFileTemp,
463: propFile);
464: } finally {
465: propOut.close();
466: }
467: } catch (Exception e) {
468: fatalError(this , "Unable to store user property file.",
469: e);
470: }
471: }
472: }
473:
474: protected synchronized void storeIdentifierProperties() {
475: if (org.myoodb.core.FileHelper.getMemoryResidentFlag() == false) {
476: org.myoodb.util.FastByteArrayOutputStream baos = new org.myoodb.util.FastByteArrayOutputStream();
477:
478: try {
479: File propFileTemp = new File(m_databaseDirectory,
480: ID_FILE_TMP);
481: OutputStream propOut = new BufferedOutputStream(baos);
482:
483: try {
484: m_identifierProperties.store(propOut,
485: "Identifier Property File.\n");
486: propOut.flush();
487:
488: RandomAccessFile raFile = new RandomAccessFile(
489: propFileTemp, FileHelper.getFileWriteMode());
490:
491: try {
492: byte[] buffer = baos.toByteArray();
493: raFile.write(buffer, 0, baos.size());
494: } finally {
495: if (raFile != null) {
496: raFile.close();
497: }
498: }
499:
500: File propFile = new File(m_databaseDirectory,
501: ID_FILE);
502: if (propFile.exists()) {
503: FileHelper.delete(propFile);
504: }
505:
506: org.myoodb.core.FileHelper.rename(propFileTemp,
507: propFile);
508: } finally {
509: propOut.close();
510: }
511: } catch (Exception e) {
512: fatalError(this ,
513: "Unable to store identifier property file.", e);
514: }
515: }
516: }
517:
518: public void startup(String username, String password, int tcpPort,
519: int tcpsPort) throws Exception {
520: try {
521: if (tcpPort != -1) {
522: m_workManager = new WorkManager(tcpPort, false);
523: m_workManager.startup();
524: m_workManager.accept();
525:
526: if (LOGGER.isInfoEnabled() == true) {
527: LOGGER.info("Database open for business");
528: }
529: }
530:
531: if (tcpsPort != -1) {
532: m_sslWorkManager = new WorkManager(tcpsPort, true);
533: m_sslWorkManager.startup();
534: m_sslWorkManager.accept();
535:
536: if (LOGGER.isInfoEnabled() == true) {
537: LOGGER.info("Database open for ssl business");
538: }
539: }
540:
541: if (getPortNumber() != -1) {
542: MyOodbDatabase db = org.myoodb.MyOodbDatabase.open(
543: "tcp://localhost:" + getPortNumber(), username,
544: password);
545: m_tunnelManager = new TunnelManager(db);
546: m_tunnelManager.startup();
547:
548: if (LOGGER.isInfoEnabled() == true) {
549: LOGGER.info("Database open for tunnel business");
550: }
551: }
552:
553: m_initializedFlag = true;
554: } catch (Exception e) {
555: LOGGER.error("Database startup (" + getPortNumber() + "/"
556: + getSslPortNumber() + ") error : ", e);
557:
558: throw e;
559: }
560: }
561:
562: public void shutdown() {
563: synchronized (this ) {
564: if (m_shuttingDownFlag == true) {
565: return;
566: }
567:
568: m_shuttingDownFlag = true;
569: }
570:
571: try {
572: if (LOGGER.isInfoEnabled() == true) {
573: LOGGER.info("shutdown...");
574: }
575:
576: if (m_sslWorkManager != null) {
577: m_sslWorkManager.shutdown();
578: m_sslWorkManager = null;
579: }
580:
581: if (m_workManager != null) {
582: m_workManager.shutdown();
583: m_workManager = null;
584: }
585:
586: if (m_storeManager != null) {
587: m_storeManager.shutdown();
588: m_storeManager = null;
589: }
590:
591: if (m_identifierManager != null) {
592: m_identifierManager.shutdown();
593: m_identifierManager = null;
594: }
595:
596: if (m_transactionManager != null) {
597: m_transactionManager.shutdown();
598: m_transactionManager = null;
599: }
600:
601: if (m_classManager != null) {
602: m_classManager.shutdown();
603: m_classManager = null;
604: }
605:
606: if (m_userManager != null) {
607: m_userManager.shutdown();
608: m_userManager = null;
609: }
610:
611: m_managers = null;
612: m_database = null;
613:
614: if (LOGGER.isInfoEnabled() == true) {
615: LOGGER.info("Halted.");
616: }
617: } catch (Exception e) {
618: fatalError(null, "Failed to shutdown: " + e, e);
619: }
620:
621: s_theManager = null;
622: }
623:
624: public void fatalError(Object sender, String msg, Exception e) {
625: if (e == null) {
626: LOGGER.error(msg);
627: } else {
628: LOGGER.error(msg, e);
629: }
630:
631: if ((s_theManager != null)
632: && (s_theManager.getShuttingdownFlag() == false)) {
633: s_theManager.shutdown();
634: }
635:
636: System.exit(1);
637: }
638:
639: public void setExitingFlag(boolean flag) {
640: m_exitingFlag = flag;
641: }
642:
643: public boolean getExitingFlag() {
644: return m_exitingFlag;
645: }
646:
647: public boolean getInitializedFlag() {
648: return m_initializedFlag;
649: }
650:
651: public boolean getShuttingdownFlag() {
652: return m_shuttingDownFlag;
653: }
654:
655: public int getPortNumber() {
656: return (m_workManager != null) ? m_workManager.getPort() : -1;
657: }
658:
659: public int getSslPortNumber() {
660: return (m_sslWorkManager != null) ? m_sslWorkManager.getPort()
661: : -1;
662: }
663:
664: public AbstractDatabase getDatabase() {
665: return m_database;
666: }
667:
668: public String getDatabaseName() {
669: return m_databaseDirectory.getName();
670: }
671:
672: public String getDatabaseDirectory() {
673: return m_databaseDirectory.getAbsolutePath() + File.separator;
674: }
675:
676: public Properties getIdentifierProperties() {
677: return m_identifierProperties;
678: }
679:
680: public Properties getUserProperties() {
681: return m_userProperties;
682: }
683:
684: public UserManager getUserManager() {
685: return m_userManager;
686: }
687:
688: public ClassManager getClassManager() {
689: return m_classManager;
690: }
691:
692: public IdentifierManager getIdentifierManager() {
693: return m_identifierManager;
694: }
695:
696: public TransactionManager getTransactionManager() {
697: return m_transactionManager;
698: }
699:
700: public AbstractStorage getStoreManager() {
701: return m_storeManager;
702: }
703:
704: public WorkManager getWorkManager() {
705: return m_workManager;
706: }
707:
708: public WorkManager getSslWorkManager() {
709: return m_sslWorkManager;
710: }
711:
712: public TunnelManager getTunnelManager() {
713: return m_tunnelManager;
714: }
715:
716: public java.lang.reflect.Method getLoginCallback() {
717: return s_loginCallback;
718: }
719:
720: public java.lang.reflect.Method getLogoutCallback() {
721: return s_logoutCallback;
722: }
723:
724: public java.lang.reflect.Method getCommitObjectCallback() {
725: return s_commitObjectCallback;
726: }
727:
728: public java.lang.reflect.Method getRollbackObjectCallback() {
729: return s_rollbackObjectCallback;
730: }
731:
732: public java.lang.reflect.Method getPreObjectMethodCallback() {
733: return s_preObjectMethodCallback;
734: }
735:
736: public java.lang.reflect.Method getPostObjectMethodCallback() {
737: return s_postObjectMethodCallback;
738: }
739: }
|