2 // Mainsoft.Web.Security.DerbyDBSchema
5 // Vladimir Krasnov (vladimirk@mainsoft.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Data.OleDb;
33 using System.Collections.Generic;
35 using System.Configuration.Provider;
36 using System.Diagnostics;
37 using Mainsoft.Web.Hosting;
39 namespace Mainsoft.Web.Security
41 internal class DerbyDBSchema
43 const string _currentSchemaVersion = "1.0";
44 static readonly object _lock = new object ();
46 #region schema string array
47 static string [] schemaElements = new string [] {
49 @"CREATE TABLE aspnet_Applications (
50 ApplicationId char(36) NOT NULL PRIMARY KEY,
51 ApplicationName varchar(256) NOT NULL UNIQUE,
52 LoweredApplicationName varchar(256) NOT NULL UNIQUE,
53 Description varchar(256)
55 @"CREATE INDEX aspnet_App_Idx ON aspnet_Applications(LoweredApplicationName)",
58 @"CREATE TABLE aspnet_Users (
59 ApplicationId char(36) NOT NULL,
60 UserId char(36) NOT NULL PRIMARY KEY,
61 UserName varchar(256) NOT NULL,
62 LoweredUserName varchar(256) NOT NULL,
63 MobileAlias varchar(16) DEFAULT NULL,
64 IsAnonymous int NOT NULL DEFAULT 0,
65 LastActivityDate timestamp NOT NULL,
67 CONSTRAINT Users_AppId_PK FOREIGN KEY (ApplicationId) REFERENCES aspnet_Applications(ApplicationId)
69 @"CREATE UNIQUE INDEX aspnet_Usr_Idx ON aspnet_Users(ApplicationId, LoweredUserName)",
70 @"CREATE INDEX aspnet_Usr_Idx2 ON aspnet_Users(ApplicationId, LastActivityDate)",
73 @"CREATE TABLE aspnet_Membership (
74 ApplicationId char(36) NOT NULL,
75 UserId char(36) NOT NULL PRIMARY KEY,
76 Password varchar(128) NOT NULL,
77 PasswordFormat int NOT NULL DEFAULT 0,
78 PasswordSalt varchar(128) NOT NULL,
79 MobilePIN varchar(16),
81 LoweredEmail varchar(256),
82 PasswordQuestion varchar(256),
83 PasswordAnswer varchar(128),
84 IsApproved int NOT NULL,
85 IsLockedOut int NOT NULL,
86 CreateDate timestamp NOT NULL,
87 LastLoginDate timestamp NOT NULL,
88 LastPasswordChangedDate timestamp NOT NULL,
89 LastLockoutDate timestamp NOT NULL,
90 FailedPasswordAttemptCount int NOT NULL,
91 FailedPwdAttemptWindowStart timestamp NOT NULL,
92 FailedPwdAnswerAttemptCount int NOT NULL,
93 FailedPwdAnswerAttWindowStart timestamp NOT NULL,
96 CONSTRAINT Member_AppId_PK FOREIGN KEY (ApplicationId) REFERENCES aspnet_Applications(ApplicationId),
97 CONSTRAINT UserId_PK FOREIGN KEY (UserId) REFERENCES aspnet_Users(UserId)
99 @"CREATE INDEX aspnet_Mbr_idx ON aspnet_Membership(ApplicationId, LoweredEmail)",
102 @"CREATE TABLE aspnet_Roles (
103 ApplicationId char(36) NOT NULL,
104 RoleId char(36) NOT NULL PRIMARY KEY,
105 RoleName varchar(256) NOT NULL,
106 LoweredRoleName varchar(256) NOT NULL,
107 Description varchar(256),
109 CONSTRAINT Roles_AppId_PK FOREIGN KEY (ApplicationId) REFERENCES aspnet_Applications(ApplicationId)
111 @"CREATE UNIQUE INDEX aspnet_Rls_idx ON aspnet_Roles(ApplicationId, LoweredRoleName)",
113 // UsersInRoles table
114 @"CREATE TABLE aspnet_UsersInRoles (
115 UserId char(36) NOT NULL,
116 RoleId char(36) NOT NULL,
118 CONSTRAINT RoleId_UserId_PK FOREIGN KEY (UserId) REFERENCES aspnet_Users (UserId),
119 CONSTRAINT UserId_RoleId_PK FOREIGN KEY (RoleId) REFERENCES aspnet_Roles (RoleId)
121 @"ALTER TABLE aspnet_UsersInRoles ADD PRIMARY KEY (UserId, RoleId)",
122 @"CREATE INDEX aspnet_UsrRls_idx ON aspnet_UsersInRoles(RoleId)",
125 @"CREATE TABLE aspnet_Profile (
126 UserId char(36) NOT NULL PRIMARY KEY,
127 PropertyNames long varchar NOT NULL,
128 PropertyValuesString long varchar NOT NULL,
129 PropertyValuesBinary blob NOT NULL,
130 LastUpdatedDate timestamp NOT NULL,
132 CONSTRAINT Profile_UserId_PK FOREIGN KEY (UserId) REFERENCES aspnet_Users (UserId)
136 //@"CREATE TABLE aspnet_Paths (
137 // ApplicationId char(36) NOT NULL,
138 // PathId char(36) NOT NULL PRIMARY KEY,
139 // Path varchar(256) NOT NULL,
140 // LoweredPath varchar(256) NOT NULL,
142 // CONSTRAINT Paths_AppId_FK FOREIGN KEY (ApplicationId) REFERENCES aspnet_Applications(ApplicationId)
144 //@"CREATE UNIQUE INDEX aspnet_Pth_idx ON aspnet_Paths(ApplicationId, LoweredPath)",
146 // Personalization tables
147 //@"CREATE TABLE aspnet_PersonalizationAllUsers (
148 // PathId char(36) NOT NULL PRIMARY KEY,
149 // PageSettings blob NOT NULL,
150 // LastUpdatedDate timestamp NOT NULL,
152 // CONSTRAINT PrsUsr_PathId_PK FOREIGN KEY (PathId) REFERENCES aspnet_Paths (PathId)
154 //@"CREATE TABLE aspnet_PersonalizationPerUser (
155 // Id char(36) NOT NULL PRIMARY KEY,
156 // PathId char(36) NOT NULL,
157 // UserId char(36) NOT NULL,
158 // PageSettings blob NOT NULL,
159 // LastUpdatedDate timestamp NOT NULL,
161 // CONSTRAINT PrsPUser_PathId_FK FOREIGN KEY (PathId) REFERENCES aspnet_Paths (PathId),
162 // CONSTRAINT PrsPUser_UserId_FK FOREIGN KEY (UserId) REFERENCES aspnet_Users (UserId)
164 //@"CREATE UNIQUE INDEX PrsPUser_idx1 ON aspnet_PersonalizationPerUser(PathId,UserId)",
165 //@"CREATE UNIQUE INDEX PrsPUser_idx2 ON aspnet_PersonalizationPerUser(UserId,PathId)"
168 @"CREATE TABLE aspnet_Version (
169 SchemaVersion varchar(10) NOT NULL
171 @"CREATE INDEX aspnet_Version_Idx ON aspnet_Version(SchemaVersion)",
172 @"INSERT INTO aspnet_Version VALUES ('1.0')"
176 public static void CheckSchema (string connectionString) {
177 string schemaVersion = GetSchemaVersion (connectionString);
178 if (schemaVersion != null) {
179 if (string.CompareOrdinal (schemaVersion, _currentSchemaVersion) == 0)
184 schemaVersion = GetSchemaVersion (connectionString);
185 if (schemaVersion == null) {
186 InitializeSchema (connectionString);
192 throw new ProviderException (String.Format ("Incorrect aspnetdb schema version: found '{0}', expected '{1}'.", schemaVersion, _currentSchemaVersion));
195 static string GetSchemaVersion (string connectionString)
197 OleDbConnection connection = new OleDbConnection (connectionString);
202 OleDbCommand cmd = new OleDbCommand ("SELECT SchemaVersion FROM aspnet_Version", connection);
205 using (OleDbDataReader reader = cmd.ExecuteReader ()) {
207 return reader.GetString (0);
216 static void InitializeSchema (string connectionString)
218 OleDbConnection connection = new OleDbConnection ();
219 connection.ConnectionString = connectionString;
224 for (int i = 0; i < schemaElements.Length; i++) {
225 OleDbCommand cmd = new OleDbCommand (schemaElements [i], connection);
226 cmd.ExecuteNonQuery ();
232 internal class DerbyUnloadManager
234 public enum DerbyShutDownPolicy
242 readonly string _connectionString;
243 readonly DerbyShutDownPolicy _policy;
245 DerbyUnloadManager (string connectionString, DerbyShutDownPolicy policy) {
246 _connectionString = connectionString;
250 public static void RegisterUnloadHandler (string connectionString, DerbyShutDownPolicy policy) {
251 if (policy == DerbyShutDownPolicy.Never)
254 if (connectionString.IndexOf("org.apache.derby.jdbc.EmbeddedDriver", StringComparison.Ordinal) < 0)
257 DerbyUnloadManager derbyMan = new DerbyUnloadManager (connectionString, policy);
258 AppDomain.CurrentDomain.DomainUnload += new EventHandler (derbyMan.UnloadHandler);
261 public void UnloadHandler (object sender, EventArgs e)
266 case DerbyShutDownPolicy.Never:
268 case DerbyShutDownPolicy.Database:
269 shutUrl = GetConnectionProperty (_connectionString, "JdbcURL");
271 case DerbyShutDownPolicy.System:
272 shutUrl = "JdbcURL=jdbc:derby:";
275 case DerbyShutDownPolicy.Default:
276 java.lang.ClassLoader contextLoader = (java.lang.ClassLoader) AppDomain.CurrentDomain.GetData (J2EEConsts.CLASS_LOADER);
277 java.lang.Class klass = contextLoader.loadClass ("org.apache.derby.jdbc.EmbeddedDriver");
281 shutUrl = (klass.getClassLoader () == contextLoader) ?
282 "JdbcURL=jdbc:derby:" : GetConnectionProperty (_connectionString, "JdbcURL");
287 const string shuttingConnection = "JdbcDriverClassName=org.apache.derby.jdbc.EmbeddedDriver;{0};shutdown=true";
289 if (!String.IsNullOrEmpty (shutUrl)) {
291 new OleDbConnection (String.Format (shuttingConnection, shutUrl)).Open ();
293 catch (Exception ex) {
294 Trace.Write (ex.ToString ());
299 static string GetConnectionProperty (string connectionString, string name) {
300 if (String.IsNullOrEmpty (connectionString))
303 string [] parts = connectionString.Split (';');
304 foreach (string part in parts)
305 if (part.StartsWith (name, StringComparison.OrdinalIgnoreCase))