1   /*
2    * Copyright 2003 - 2013 The eFaps Team
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Revision:        $Rev$
17   * Last Changed:    $Date$
18   * Last Changed By: $Author$
19   */
20  
21  package org.efaps.admin.user;
22  
23  import java.io.Serializable;
24  import java.sql.PreparedStatement;
25  import java.sql.SQLException;
26  import java.sql.Statement;
27  import java.util.UUID;
28  
29  import org.efaps.admin.AbstractAdminObject;
30  import org.efaps.admin.datamodel.Type;
31  import org.efaps.ci.CIAdminUser;
32  import org.efaps.db.Context;
33  import org.efaps.db.MultiPrintQuery;
34  import org.efaps.db.QueryBuilder;
35  import org.efaps.db.transaction.ConnectionResource;
36  import org.efaps.util.EFapsException;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
41  
42  /**
43   * @author The eFaps Team
44   * @version $Id$
45   */
46  public abstract class AbstractUserObject
47      extends AbstractAdminObject
48      implements Serializable
49  {
50      /**
51       * Needed for serialization.
52       */
53      private static final long serialVersionUID = 1L;
54  
55      /**
56       * Logging instance used to give logging information of this class.
57       */
58      private static final Logger LOG = LoggerFactory.getLogger(AbstractUserObject.class);
59  
60      /**
61       * Instance variable holding the Status (active, inactive).
62       */
63      private boolean status;
64  
65      /**
66       * Constructor to set instance variables of the user object.
67       *
68       * @param _id       id to set
69       * @param _uuid     uuid to set
70       * @param _name     name to set
71       * @param _status   status to set
72       */
73      protected AbstractUserObject(final long _id,
74                                   final String _uuid,
75                                   final String _name,
76                                   final boolean _status)
77      {
78          super(_id, _uuid, _name);
79          this.status = _status;
80      }
81  
82      /**
83       * Checks, if the given person is assigned to this user object. The method
84       * must be overwritten by the special implementations.
85       *
86       * @param _person person to test
87       * @return <i>true</i> if the person is assigned to this user object,
88       *         otherwise <i>false</i>
89       * @see #persons
90       * @see #getPersons
91       */
92      public abstract boolean hasChildPerson(final Person _person);
93  
94      /**
95       * Checks, if the context user is assigned to this user object. The instance
96       * method uses {@link #hasChildPerson} to test this.
97       *
98       * @see #hasChildPerson
99       * @return true if person is assigned
100      */
101     public boolean isAssigned()
102     {
103         boolean ret = false;
104         try {
105             ret = hasChildPerson(Context.getThreadContext().getPerson());
106         } catch (final EFapsException e) {
107             AbstractUserObject.LOG.error("could not read Person ", e);
108         }
109         return ret;
110     }
111 
112     /**
113      * Assign this user object to the given JAAS system under the given JAAS
114      * key.
115      *
116      * @param _jaasSystem   JAAS system to which the person is assigned
117      * @param _jaasKey      key under which the person is know in the JAAS
118      *                      system
119      * @throws EFapsException if the assignment could not be made
120      */
121     @SuppressFBWarnings("SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING")
122     public void assignToJAASSystem(final JAASSystem _jaasSystem,
123                                    final String _jaasKey)
124         throws EFapsException
125     {
126         ConnectionResource rsrc = null;
127         try {
128             final Context context = Context.getThreadContext();
129             rsrc = context.getConnectionResource();
130             final Type keyType = CIAdminUser.JAASKey.getType();
131 
132             PreparedStatement stmt = null;
133             final StringBuilder cmd = new StringBuilder();
134             try {
135                 long keyId = 0;
136                 if (Context.getDbType().supportsGetGeneratedKeys()) {
137                     cmd.append("insert into ").append(keyType.getMainTable().getSqlTable()).append(
138                                     "(KEY,CREATOR,CREATED,MODIFIER,MODIFIED,").append("USERABSTRACT,USERJAASSYSTEM) ")
139                                     .append("values (");
140                 } else {
141                     keyId = Context.getDbType().getNewId(rsrc.getConnection(), keyType.getMainTable().getSqlTable(),
142                                     "ID");
143                     cmd.append("insert into ").append(keyType.getMainTable().getSqlTable()).append(
144                                     "(ID,KEY,CREATOR,CREATED,MODIFIER,MODIFIED,").append(
145                                     "USERABSTRACT,USERJAASSYSTEM) ").append("values (").append(keyId).append(",");
146                 }
147                 cmd.append("'").append(_jaasKey).append("',").append(context.getPersonId()).append(",").append(
148                                 Context.getDbType().getCurrentTimeStamp()).append(",").append(context.getPersonId())
149                                 .append(",").append(Context.getDbType().getCurrentTimeStamp()).append(",").append(
150                                                 getId()).append(",").append(_jaasSystem.getId()).append(")");
151 
152                 stmt = rsrc.getConnection().prepareStatement(cmd.toString());
153                 final int rows = stmt.executeUpdate();
154                 if (rows == 0) {
155                     AbstractUserObject.LOG.error("could not execute '" + cmd.toString()
156                             + "' for JAAS system '" + _jaasSystem.getName()
157                             + "' for user object '" + toString() + "' with JAAS key '" + _jaasKey + "'");
158                     throw new EFapsException(getClass(), "assignToJAASSystem.NotInserted", _jaasSystem.getName(),
159                                     _jaasKey, toString());
160                 }
161             } catch (final SQLException e) {
162                 AbstractUserObject.LOG.error("could not execute '" + cmd.toString()
163                         + "' to assign user object '" + toString()
164                         + "' with JAAS key '" + _jaasKey + "' to JAAS system '" + _jaasSystem.getName() + "'", e);
165                 throw new EFapsException(getClass(), "assignToJAASSystem.SQLException", e, cmd.toString(), _jaasSystem
166                                 .getName(), _jaasKey, toString());
167             } finally {
168                 try {
169                     if (stmt != null) {
170                         stmt.close();
171                     }
172                 } catch (final SQLException e) {
173                     AbstractUserObject.LOG.error("Could not close a statement.", e);
174                 }
175             }
176 
177             rsrc.commit();
178         } finally {
179             if (rsrc != null && rsrc.isOpened()) {
180                 rsrc.abort();
181             }
182         }
183     }
184 
185     /**
186      * Assign this user object to the given user object for given JAAS system.
187      *
188      * @param _assignType   type used to assign (in other words the
189      *                      relationship type)
190      * @param _jaasSystem   JAAS system for which this user object is assigned
191      *                      to the given object
192      * @param _object user object to which this user object is assigned
193      * @throws EFapsException if assignment could not be done
194      */
195     @SuppressFBWarnings("SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING")
196     protected void assignToUserObjectInDb(final Type _assignType,
197                                           final JAASSystem _jaasSystem,
198                                           final AbstractUserObject _object)
199         throws EFapsException
200     {
201         ConnectionResource rsrc = null;
202         try {
203             final Context context = Context.getThreadContext();
204             rsrc = context.getConnectionResource();
205 
206             Statement stmt = null;
207             final StringBuilder cmd = new StringBuilder();
208             try {
209 
210                 cmd.append("insert into ").append(_assignType.getMainTable().getSqlTable()).append("(");
211                 long keyId = 0;
212                 if (!Context.getDbType().supportsGetGeneratedKeys()) {
213                     keyId = Context.getDbType().getNewId(rsrc.getConnection(),
214                                     _assignType.getMainTable().getSqlTable(), "ID");
215                     cmd.append("ID,");
216                 }
217                 cmd.append("TYPEID,CREATOR,CREATED,MODIFIER,MODIFIED,").append(
218                                 "USERABSTRACTFROM,USERABSTRACTTO,USERJAASSYSTEM) ").append("values (");
219                 if (keyId != 0) {
220                     cmd.append(keyId).append(",");
221                 }
222                 cmd.append(_assignType.getId()).append(",").append(context.getPersonId()).append(",").append(
223                                 Context.getDbType().getCurrentTimeStamp()).append(",").append(context.getPersonId())
224                                 .append(",").append(Context.getDbType().getCurrentTimeStamp()).append(",").append(
225                                                 getId()).append(",").append(_object.getId()).append(",").append(
226                                                 _jaasSystem.getId()).append(")");
227 
228                 stmt = rsrc.getConnection().createStatement();
229                 final int rows = stmt.executeUpdate(cmd.toString());
230                 if (rows == 0) {
231                     AbstractUserObject.LOG.error("could not execute '" + cmd.toString()
232                             + "' to assign user object '" + toString()
233                             + "' to object '" + _object + "' for JAAS system '" + _jaasSystem + "' ");
234                     throw new EFapsException(getClass(), "assignInDb.NotInserted", _jaasSystem.getName(), _object
235                                     .getName(), getName());
236                 }
237             } catch (final SQLException e) {
238                 AbstractUserObject.LOG.error("could not execute '" + cmd.toString()
239                         + "' to assign user object '" + toString()
240                         + "' to object '" + _object + "' for JAAS system '" + _jaasSystem + "' ", e);
241                 throw new EFapsException(getClass(), "assignInDb.SQLException", e, cmd.toString(), getName());
242             } finally {
243                 try {
244                     if (stmt != null) {
245                         stmt.close();
246                     }
247                 } catch (final SQLException e) {
248                     AbstractUserObject.LOG.error("Could not close a statement.", e);
249                 }
250             }
251             rsrc.commit();
252         } finally {
253             if (rsrc != null && rsrc.isOpened()) {
254                 rsrc.abort();
255             }
256         }
257     }
258 
259     /**
260      * Unassign this user object from the given user object for given JAAS
261      * system.
262      *
263      * @param _unassignType type used to unassign (in other words the
264      *            relationship type)
265      * @param _jaasSystem JAAS system for which this user object is unassigned
266      *            from given object
267      * @param _object user object from which this user object is unassigned
268      * @throws EFapsException if unassignment could not be done
269      */
270     protected void unassignFromUserObjectInDb(final Type _unassignType,
271                                               final JAASSystem _jaasSystem,
272                                               final AbstractUserObject _object)
273         throws EFapsException
274     {
275 
276         ConnectionResource rsrc = null;
277         try {
278             rsrc = Context.getThreadContext().getConnectionResource();
279             Statement stmt = null;
280             final StringBuilder cmd = new StringBuilder();
281             try {
282                 cmd.append("delete from ").append(_unassignType.getMainTable().getSqlTable()).append(" ").append(
283                                 "where USERJAASSYSTEM=").append(_jaasSystem.getId()).append(" ").append(
284                                 "and USERABSTRACTFROM=").append(getId()).append(" ").append("and USERABSTRACTTO=")
285                                 .append(_object.getId());
286 
287                 stmt = rsrc.getConnection().createStatement();
288                 stmt.executeUpdate(cmd.toString());
289 
290             } catch (final SQLException e) {
291                 AbstractUserObject.LOG.error("could not execute '" + cmd.toString()
292                         + "' to unassign user object '" + toString()
293                         + "' from object '" + _object + "' for JAAS system '" + _jaasSystem + "' ", e);
294                 throw new EFapsException(getClass(), "unassignFromUserObjectInDb.SQLException", e, cmd.toString(),
295                                 getName());
296             } finally {
297                 try {
298                     if (stmt != null) {
299                         stmt.close();
300                     }
301                 } catch (final SQLException e) {
302                     AbstractUserObject.LOG.error("Could not close a statement.", e);
303                 }
304             }
305             rsrc.commit();
306         } finally {
307             if (rsrc != null && rsrc.isOpened()) {
308                 rsrc.abort();
309             }
310         }
311     }
312 
313     /**
314      * This is the getter method for the instance variable {@link #status}.
315      *
316      * @return value of instance variable {@link #status}
317      */
318     public boolean getStatus()
319     {
320         return this.status;
321     }
322 
323     /**
324      * This is the setter method for the instance variable {@link #status}.
325      *
326      * @param _status the status to set
327      */
328     public void setStatus(final boolean _status)
329     {
330         this.status = _status;
331     }
332 
333     /**
334      * Get the note belonging to this UserObject.
335      * <b>Careful. Executes Query against the Database and therefore might be slow.</b>
336      * @return the note belonging to the UserObject
337      * @throws EFapsException on error during reading
338      */
339     public String getNote()
340         throws EFapsException
341     {
342         String ret = "";
343         final QueryBuilder queryBldr = new QueryBuilder(CIAdminUser.Abstract);
344         queryBldr.addWhereAttrEqValue(CIAdminUser.Abstract.ID, getId());
345         final MultiPrintQuery multi = queryBldr.getPrint();
346         multi.addAttribute(CIAdminUser.Abstract.Note);
347         if (multi.execute()) {
348             multi.next();
349             ret = multi.getAttribute(CIAdminUser.Abstract.Note);
350         }
351         return ret;
352     }
353 
354     /**
355      * Method to set the status of a UserObject in the eFaps Database.
356      *
357      * @param _status status to set
358      * @throws EFapsException on error
359      */
360     protected void setStatusInDB(final boolean _status)
361         throws EFapsException
362     {
363         ConnectionResource rsrc = null;
364         try {
365             final Context context = Context.getThreadContext();
366             rsrc = context.getConnectionResource();
367 
368             PreparedStatement stmt = null;
369             final StringBuilder cmd = new StringBuilder();
370             try {
371 
372                 cmd.append(" update T_USERABSTRACT set STATUS=? where ID=").append(getId());
373                 stmt = rsrc.getConnection().prepareStatement(cmd.toString());
374                 stmt.setBoolean(1, _status);
375                 final int rows = stmt.executeUpdate();
376                 if (rows == 0) {
377                     AbstractUserObject.LOG.error("could not execute '" + cmd.toString()
378                             + "' to update status information for person '" + toString() + "'");
379                     throw new EFapsException(getClass(), "setStatusInDB.NotUpdated", cmd.toString(), getName());
380                 }
381             } catch (final SQLException e) {
382                 AbstractUserObject.LOG.error("could not execute '" + cmd.toString()
383                         + "' to update status information for person '" + toString() + "'", e);
384                 throw new EFapsException(getClass(), "setStatusInDB.SQLException", e, cmd.toString(), getName());
385             } finally {
386                 try {
387                     if (stmt != null) {
388                         stmt.close();
389                     }
390                 } catch (final SQLException e) {
391                     throw new EFapsException(getClass(), "setStatusInDB.SQLException", e, cmd.toString(), getName());
392                 }
393             }
394             rsrc.commit();
395         } finally {
396             if (rsrc != null && rsrc.isOpened()) {
397                 rsrc.abort();
398             }
399         }
400     }
401 
402     /**
403      * Returns for given parameter <i>_uuid</i> the instance of class
404      * {@link AbstractUserObject}. The returned AbstractUserObject can be a
405      * {@link Role}, {@link Group}, {@link Company}, {@link Consortium}
406      * or {@link Person}. It is searched in the given sequence. User is searched last
407      * due to the reason that it is the only object that is not always stored
408      * in a cache an might produce queries against the DataBase
409      *
410      * @param _uuid UUID to search in the cache
411      * @return instance of class {@link AbstractUserObject}
412      * @throws EFapsException on error
413      */
414     public static AbstractUserObject getUserObject(final UUID _uuid)
415         throws EFapsException
416     {
417         AbstractUserObject ret = Role.get(_uuid);
418         if (ret == null) {
419             ret = Group.get(_uuid);
420         }
421         if (ret == null) {
422             ret = Company.get(_uuid);
423         }
424         if (ret == null) {
425             ret = Consortium.get(_uuid);
426         }
427         if (ret == null) {
428             ret = Person.get(_uuid);
429         }
430         return ret;
431     }
432 
433     /**
434      * Returns for given parameter <i>_id</i> the instance of class
435      * {@link AbstractUserObject}. The returned AbstractUserObject can be a
436      * {@link Role}, {@link Group}, {@link Company}, {@link Consortium}
437      * or {@link Person}. It is searched in the given sequence. User is searched last
438      * due to the reason that it is the only object that is not always stored
439      * in a cache an might produce queries against the DataBase
440      *
441      * @param _id id to search in the cache
442      * @return instance of class {@link AbstractUserObject}
443      * @throws EFapsException on error
444      */
445     public static AbstractUserObject getUserObject(final long _id)
446         throws EFapsException
447     {
448         AbstractUserObject ret = Role.get(_id);
449         if (ret == null) {
450             ret = Group.get(_id);
451         }
452         if (ret == null) {
453             ret = Company.get(_id);
454         }
455         if (ret == null) {
456             ret = Consortium.get(_id);
457         }
458         if (ret == null) {
459             ret = Person.get(_id);
460         }
461         return ret;
462     }
463 
464     /**
465      * Returns for given parameter <i>_name</i> the instance of class
466      * {@link AbstractUserObject}.The returned AbstractUserObject can be a
467      * {@link Role}, {@link Group}, {@link Company}, {@link Consortium}
468      * or {@link Person}. It is searched in the given sequence. User is searched
469      * last due to the reason that it is the only object that is not always stored
470      * in a cache an might produce queries against the DataBase
471      *
472      * @param _name name to search in the cache
473      * @return instance of class {@link AbstractUserObject}
474      * @throws EFapsException on error
475      */
476     public static AbstractUserObject getUserObject(final String _name)
477         throws EFapsException
478     {
479         AbstractUserObject ret = Role.get(_name);
480         if (ret == null) {
481             ret = Group.get(_name);
482         }
483         if (ret == null) {
484             ret = Company.get(_name);
485         }
486         if (ret == null) {
487             ret = Consortium.get(_name);
488         }
489         if (ret == null) {
490             ret = Person.get(_name);
491         }
492         return ret;
493     }
494 }