001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. The ASF licenses this file to You
004: * under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License. For additional information regarding
015: * copyright in this work, please see the NOTICE file in the top level
016: * directory of this distribution.
017: */
018: package org.apache.roller.webservices.adminapi;
019:
020: import java.io.IOException;
021: import java.io.Reader;
022: import javax.servlet.http.HttpServletRequest;
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025: import org.apache.roller.config.RollerConfig;
026: import org.apache.roller.business.Roller;
027: import org.apache.roller.business.RollerFactory;
028: import org.apache.roller.ui.core.RollerContext;
029: import org.apache.roller.webservices.adminapi.sdk.EntrySet;
030: import java.util.regex.Pattern;
031: import java.util.regex.Matcher;
032: import org.apache.roller.RollerException;
033: import org.apache.roller.config.RollerRuntimeConfig;
034: import org.apache.roller.business.UserManager;
035: import org.apache.roller.pojos.UserData;
036: import org.apache.roller.pojos.WebsiteData;
037: import org.apache.roller.webservices.adminapi.sdk.UnexpectedRootElementException;
038: import org.jdom.Document;
039: import org.jdom.JDOMException;
040: import org.jdom.input.SAXBuilder;
041:
042: /**
043: * This class is the abstract notion of an AAPP request handler.
044: * It processes HTTP requests for each of the four HTTP verbs:
045: * GET, POST, PUT, DELETE, for a given weblog resource.
046: */
047: abstract class Handler {
048: protected static final String ENDPOINT = "/aapp";
049:
050: static class URI {
051: private static Pattern PATHINFO_PATTERN = Pattern
052: .compile("^/(users|weblogs|members)(?:/(.*))?$");
053:
054: private String type;
055: private String entryId;
056:
057: public URI(HttpServletRequest request)
058: throws BadRequestException {
059: String pi = request.getPathInfo();
060:
061: if (pi == null || pi.length() == 0) {
062: type = null;
063: entryId = null;
064: } else {
065: Matcher m = PATHINFO_PATTERN.matcher(pi);
066: if (!m.matches()) {
067: throw new BadRequestException(
068: "ERROR: Invalid path info: " + pi);
069: }
070:
071: type = m.group(1);
072: entryId = m.group(2);
073: }
074: }
075:
076: public String getType() {
077: return type;
078: }
079:
080: public String getEntryId() {
081: return entryId;
082: }
083:
084: public boolean isIntrospection() {
085: return getEntryId() == null && type == null;
086: }
087:
088: public boolean isCollection() {
089: return getEntryId() == null && type != null;
090: }
091:
092: public boolean isEntry() {
093: return getEntryId() != null && type != null;
094: }
095: }
096:
097: protected static final Log logger = LogFactory.getFactory()
098: .getInstance(Handler.class);
099:
100: private HttpServletRequest request;
101: private Roller roller;
102: private RollerContext rollerContext;
103: private String userName;
104: private URI uri;
105: private String urlPrefix;
106:
107: /** Get a Handler object implementation based on the given request. */
108: public static Handler getHandler(HttpServletRequest req)
109: throws HandlerException {
110: boolean enabled = RollerConfig
111: .getBooleanProperty("webservices.adminprotocol.enabled");
112: if (!enabled) {
113: throw new NotAllowedException(
114: "ERROR: Admin protocol not enabled");
115: }
116:
117: URI uri = new URI(req);
118: Handler handler;
119:
120: if (uri.isIntrospection()) {
121: handler = new IntrospectionHandler(req);
122: } else if (uri.isCollection() || uri.isEntry()) {
123: String type = uri.getType();
124: if (type.equals(EntrySet.Types.WEBLOGS)) {
125: handler = new RollerWeblogHandler(req);
126: } else if (type.equals(EntrySet.Types.USERS)) {
127: handler = new RollerUserHandler(req);
128: } else if (type.equals(EntrySet.Types.MEMBERS)) {
129: handler = new RollerMemberHandler(req);
130: } else {
131: throw new BadRequestException("ERROR: Unknown type: "
132: + uri.getType());
133: }
134: } else {
135: throw new BadRequestException("ERROR: Unknown URI type");
136: }
137:
138: return handler;
139: }
140:
141: public Handler(HttpServletRequest request) throws HandlerException {
142: this .request = request;
143: this .uri = new URI(request);
144: this .rollerContext = RollerContext.getRollerContext();
145: this .roller = RollerFactory.getRoller();
146: //TODO: is this the right thing to do? hardcode roller-services?
147: this .urlPrefix = RollerRuntimeConfig.getAbsoluteContextURL()
148: + "/roller-services" + ENDPOINT;
149:
150: // TODO: decide what to do about authentication, is WSSE going to fly?
151: //Authenticator auth = new WSSEAuthenticator(request);
152: Authenticator auth = new BasicAuthenticator(request);
153: auth.authenticate();
154: setUserName(auth.getUserName());
155: }
156:
157: /**
158: * Get the authenticated user name.
159: * If this method returns null, then authentication has failed.
160: */
161: public String getUserName() {
162: return userName;
163: }
164:
165: private void setUserName(String userName) {
166: this .userName = userName;
167: }
168:
169: /** Process an HTTP GET request. */
170: public abstract EntrySet processGet() throws HandlerException;
171:
172: /** Process an HTTP POST request. */
173: public abstract EntrySet processPost(Reader r)
174: throws HandlerException;
175:
176: /** Process an HTTP PUT request. */
177: public abstract EntrySet processPut(Reader r)
178: throws HandlerException;
179:
180: /** Process an HTTP DELETE request. */
181: public abstract EntrySet processDelete() throws HandlerException;
182:
183: protected URI getUri() {
184: return uri;
185: }
186:
187: protected HttpServletRequest getRequest() {
188: return request;
189: }
190:
191: protected RollerContext getRollerContext() {
192: return rollerContext;
193: }
194:
195: protected Roller getRoller() {
196: return roller;
197: }
198:
199: protected String getUrlPrefix() {
200: return urlPrefix;
201: }
202:
203: protected abstract EntrySet getEntrySet(Document d)
204: throws UnexpectedRootElementException;
205:
206: protected EntrySet getEntrySet(Reader r) throws HandlerException {
207: try {
208: SAXBuilder builder = new SAXBuilder();
209: Document d = builder.build(r);
210: EntrySet c = getEntrySet(d);
211:
212: return c;
213: } catch (UnexpectedRootElementException ure) {
214: throw new BadRequestException(
215: "ERROR: Failed to parse content", ure);
216: } catch (JDOMException jde) {
217: throw new BadRequestException(
218: "ERROR: Failed to parse content", jde);
219: } catch (IOException ioe) {
220: throw new InternalException(
221: "ERROR: Failed to parse content", ioe);
222: }
223: }
224:
225: protected WebsiteData getWebsiteData(String handle)
226: throws NotFoundException, InternalException {
227: try {
228: WebsiteData wd = getRoller().getUserManager()
229: .getWebsiteByHandle(handle, Boolean.TRUE);
230: if (wd == null) {
231: wd = getRoller().getUserManager().getWebsiteByHandle(
232: handle, Boolean.FALSE);
233: }
234: if (wd == null) {
235: throw new NotFoundException(
236: "ERROR: Unknown weblog handle: " + handle);
237: }
238:
239: return wd;
240: } catch (RollerException re) {
241: throw new InternalException("ERROR: Could not get weblog: "
242: + handle, re);
243: }
244: }
245:
246: protected UserData getUserData(String name)
247: throws NotFoundException, InternalException {
248: try {
249: UserManager mgr = getRoller().getUserManager();
250: UserData ud = mgr.getUserByUserName(name, Boolean.TRUE);
251: if (ud == null) {
252: ud = mgr.getUserByUserName(name, Boolean.FALSE);
253: }
254: if (ud == null) {
255: throw new NotFoundException("ERROR: Unknown user: "
256: + name);
257: }
258:
259: return ud;
260: } catch (RollerException re) {
261: throw new InternalException("ERROR: Could not get user: "
262: + name, re);
263: }
264: }
265:
266: }
|