001: /*
002: * Copyright 2005-2007 Noelios Consulting.
003: *
004: * The contents of this file are subject to the terms of the Common Development
005: * and Distribution License (the "License"). You may not use this file except in
006: * compliance with the License.
007: *
008: * You can obtain a copy of the license at
009: * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
010: * language governing permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL HEADER in each file and
013: * include the License file at http://www.opensource.org/licenses/cddl1.txt If
014: * applicable, add the following below this CDDL HEADER, with the fields
015: * enclosed by brackets "[]" replaced with your own identifying information:
016: * Portions Copyright [yyyy] [name of copyright owner]
017: */
018:
019: package org.restlet.example.book.rest.ch7;
020:
021: import java.util.List;
022:
023: import org.restlet.Context;
024: import org.restlet.data.ChallengeRequest;
025: import org.restlet.data.ChallengeResponse;
026: import org.restlet.data.ChallengeScheme;
027: import org.restlet.data.Form;
028: import org.restlet.data.MediaType;
029: import org.restlet.data.Request;
030: import org.restlet.data.Response;
031: import org.restlet.data.Status;
032: import org.restlet.resource.Representation;
033: import org.restlet.resource.Resource;
034: import org.restlet.resource.StringRepresentation;
035: import org.restlet.resource.Variant;
036:
037: import com.db4o.ObjectContainer;
038: import com.db4o.query.Predicate;
039:
040: /**
041: * Resource for a persistent user.
042: *
043: * @author Jerome Louvel (contact@noelios.com)
044: */
045: public class UserResource extends Resource {
046:
047: private String login;
048:
049: private String password;
050:
051: private User user;
052:
053: private String userName;
054:
055: /**
056: * Constructor.
057: *
058: * @param context
059: * The parent context.
060: * @param request
061: * The request to handle.
062: * @param response
063: * The response to return.
064: */
065: public UserResource(Context context, Request request,
066: Response response) {
067: super (context, request, response);
068: this .userName = (String) request.getAttributes()
069: .get("username");
070: ChallengeResponse cr = request.getChallengeResponse();
071: this .login = (cr != null) ? cr.getIdentifier() : null;
072: this .password = (cr != null) ? new String(cr.getSecret())
073: : null;
074: this .user = findUser();
075:
076: if (user != null) {
077: getVariants().add(new Variant(MediaType.TEXT_PLAIN));
078: }
079: }
080:
081: @Override
082: public boolean allowDelete() {
083: return true;
084: }
085:
086: @Override
087: public boolean allowPut() {
088: return true;
089: }
090:
091: /**
092: * Updates the response to challenge the client for credentials.
093: */
094: public void challenge() {
095: getResponse().setStatus(Status.CLIENT_ERROR_CONFLICT);
096: getResponse().setChallengeRequest(
097: new ChallengeRequest(ChallengeScheme.HTTP_BASIC,
098: "Restlet"));
099: }
100:
101: /**
102: * Check the authorization credentials.
103: *
104: * @return 1 if authentication ok, 0 if it is missing, -1 if it is wrong
105: */
106: public int checkAuthorization() {
107: int result = 0;
108:
109: if (this .user != null) {
110: if ((this .login != null) && (this .password != null)) {
111: // Credentials provided
112: if (this .userName.equals(this .login)
113: && this .password
114: .equals(this .user.getPassword())) {
115: result = 1;
116: } else {
117: result = -1;
118: }
119: }
120: }
121:
122: return result;
123: }
124:
125: @Override
126: public void delete() {
127: switch (checkAuthorization()) {
128: case 1:
129: // Delete all associated bookmarks
130: for (Bookmark bookmark : this .user.getBookmarks()) {
131: getContainer().delete(bookmark);
132: }
133:
134: // Delete the parent user
135: getContainer().delete(this .user);
136:
137: // Commit the changes
138: getContainer().commit();
139: getResponse().setStatus(Status.SUCCESS_OK);
140: break;
141: case 0:
142: // No authentication provided
143: challenge();
144: break;
145: case -1:
146: // Wrong authenticaiton provided
147: getResponse().setStatus(Status.CLIENT_ERROR_UNAUTHORIZED);
148: break;
149: }
150: }
151:
152: /**
153: * Finds the associated user.
154: *
155: * @return The user found or null.
156: */
157: public User findUser() {
158: User result = null;
159:
160: if (userName != null) {
161: // Create the query predicate
162: Predicate<User> predicate = new Predicate<User>() {
163: private static final long serialVersionUID = 1L;
164:
165: @Override
166: public boolean match(User candidate) {
167: return userName.equals(candidate.getName());
168: }
169: };
170:
171: // Query the database and get the first result
172: List<User> users = getContainer().query(predicate);
173: if ((users != null) && (users.size() > 0)) {
174: result = users.get(0);
175: }
176: }
177:
178: return result;
179: }
180:
181: /**
182: * Returns the parent application.
183: *
184: * @return the parent application.
185: */
186: public Application getApplication() {
187: return (Application) getContext().getAttributes().get(
188: Application.KEY);
189: }
190:
191: /**
192: * Returns the database container.
193: *
194: * @return the database container.
195: */
196: public ObjectContainer getContainer() {
197: return getApplication().getContainer();
198: }
199:
200: @Override
201: public Representation getRepresentation(Variant variant) {
202: Representation result = null;
203:
204: if ((variant != null)
205: && variant.getMediaType().equals(MediaType.TEXT_PLAIN)) {
206: // Creates a text representation
207: StringBuilder sb = new StringBuilder();
208: sb.append("------------\n");
209: sb.append("User details\n");
210: sb.append("------------\n\n");
211: sb.append("Name: ").append(this .user.getFullName())
212: .append('\n');
213: sb.append("Email: ").append(this .user.getEmail()).append(
214: '\n');
215: result = new StringRepresentation(sb);
216: }
217:
218: return result;
219: }
220:
221: /**
222: * Returns the associated user.
223: *
224: * @return The associated user.
225: */
226: public User getUser() {
227: return this .user;
228: }
229:
230: @Override
231: public void put(Representation entity) {
232: if (entity.getMediaType().equals(
233: MediaType.APPLICATION_WWW_FORM, true)) {
234: boolean canSet = true;
235:
236: if (getUser() == null) {
237: // The user doesn't exist, create it
238: setUser(new User());
239: getUser().setName(this .userName);
240: getResponse().setStatus(Status.SUCCESS_CREATED);
241: } else {
242: // The user already exists, check the authentication
243: switch (checkAuthorization()) {
244: case 1:
245: getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
246: break;
247: case 0:
248: // No authentication provided
249: challenge();
250: canSet = false;
251: break;
252: case -1:
253: // Wrong authenticaiton provided
254: getResponse().setStatus(
255: Status.CLIENT_ERROR_UNAUTHORIZED);
256: canSet = false;
257: break;
258: }
259: }
260:
261: if (canSet) {
262: // Parse the entity as a web form
263: Form form = new Form(entity);
264: getUser().setEmail(form.getFirstValue("user[email]"));
265: getUser().setFullName(
266: form.getFirstValue("user[full_name]"));
267: getUser().setPassword(
268: form.getFirstValue("user[password]"));
269:
270: // Commit the changes
271: getContainer().set(getUser());
272: getContainer().commit();
273: }
274: }
275: }
276:
277: /**
278: * Sets the associated user.
279: *
280: * @param user
281: * The user to set.
282: */
283: public void setUser(User user) {
284: this.user = user;
285: }
286:
287: }
|