/* Copyright 2004-2014 Jim Voris
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.qumasoft.server;
import com.qumasoft.qvcslib.ArchiveDirManagerInterface;
import com.qumasoft.qvcslib.ServerResponseFactory;
import com.qumasoft.qvcslib.Utility;
import com.qumasoft.qvcslib.response.ServerResponseLogin;
import com.qumasoft.qvcslib.response.ServerResponseMessage;
import com.qumasoft.server.clientrequest.ClientRequestFactory;
import com.qumasoft.server.clientrequest.ClientRequestInterface;
import com.qumasoft.server.clientrequest.ClientRequestLogin;
import java.io.IOException;
import java.net.Socket;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
class ServerWorker implements Runnable {
// Create our logger object
private static final Logger LOGGER = Logger.getLogger("com.qumasoft.server");
/*
* Socket to client we're handling
*/
private final Socket workerSocket;
ServerWorker(Socket socket) {
this.workerSocket = socket;
}
@Override
public void run() {
handleClientRequests();
LOGGER.log(Level.INFO, "Returned from handleClientRequests for thread: [" + Thread.currentThread().getName() + "]");
}
private void handleClientRequests() {
String connectedTo = null;
ServerResponseFactory responseFactory = null;
ClientRequestFactory requestFactory;
try {
requestFactory = new ClientRequestFactory(workerSocket.getInputStream());
responseFactory = new ServerResponseFactory(workerSocket.getOutputStream(), workerSocket.getPort(), workerSocket.getInetAddress().getHostAddress());
connectedTo = workerSocket.getInetAddress().getHostAddress();
LOGGER.log(Level.INFO, "Connected to: [" + connectedTo + "]");
while (!ServerResponseFactory.getShutdownInProgress() && responseFactory.getConnectionAliveFlag()) {
try {
ClientRequestInterface clientRequest = requestFactory.createClientRequest(responseFactory);
if (clientRequest != null) {
java.io.Serializable returnObject = clientRequest.execute(requestFactory.getUserName(), responseFactory);
if (clientRequest instanceof ClientRequestLogin) {
ServerResponseLogin serverResponseLogin = (ServerResponseLogin) returnObject;
if (serverResponseLogin.getLoginResult()) {
requestFactory.setIsUserLoggedIn(true);
requestFactory.setUserName(serverResponseLogin.getUserName());
responseFactory.setIsUserLoggedIn(true);
responseFactory.setUserName(serverResponseLogin.getUserName());
ClientRequestLogin loginRequest = (ClientRequestLogin) clientRequest;
responseFactory.setServerName(loginRequest.getServerName());
requestFactory.setClientVersionMatchesFlag(serverResponseLogin.getVersionsMatchFlag());
QVCSEnterpriseServer.getConnectedUsersCollection().add(responseFactory);
}
}
// Send the response back to the client.
responseFactory.createServerResponse(returnObject);
// If this was a login request that succeeded, we also
// need to send the list of projects for this user.
if (clientRequest instanceof ClientRequestLogin) {
ClientRequestLogin clientRequestLogin = (ClientRequestLogin) clientRequest;
ServerResponseMessage message;
if (!responseFactory.getIsUserLoggedIn()) {
// The user failed to login. Report the problem to the user.
if (clientRequestLogin.getAuthenticationFailedFlag()) {
message = new ServerResponseMessage("Invalid username/password", null, null, null, ServerResponseMessage.HIGH_PRIORITY);
responseFactory.createServerResponse(message);
}
} else {
// Report any status information back to the user.
if (clientRequestLogin.getMessage() != null) {
message = new ServerResponseMessage(clientRequestLogin.getMessage(), null, null, null, ServerResponseMessage.HIGH_PRIORITY);
responseFactory.createServerResponse(message);
}
}
}
} else {
LOGGER.log(Level.INFO, "clientRequest is null!!");
LOGGER.log(Level.INFO, "Breaking connection to: [" + connectedTo + "]");
break;
}
} catch (QVCSShutdownException e) {
// We are shutting down this server.
LOGGER.log(Level.INFO, "Shutting down server at request from: [" + connectedTo + "]");
break;
} catch (RuntimeException e) {
LOGGER.log(Level.INFO, "Runtime exception -- breaking connection to: [" + connectedTo + "]");
LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e));
break;
} catch (Exception e) {
LOGGER.log(Level.INFO, "Exception -- breaking connection to: [" + connectedTo + "]");
LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e));
break;
}
}
} catch (IOException e) {
LOGGER.log(Level.INFO, "Breaking connection to: [" + connectedTo + "]");
LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e));
} finally {
try {
LOGGER.log(Level.INFO, "Server closing socket for: [" + connectedTo + "]");
workerSocket.close();
// The connection to the client is gone. Remove the response
// factory as a listener for any archive directory managers
// so we don't waste time trying to inform a client that we
// can no longer talk to.
if (responseFactory != null) {
Set<ArchiveDirManagerInterface> directoryManagers = responseFactory.getDirectoryManagers();
Iterator<ArchiveDirManagerInterface> it = directoryManagers.iterator();
while (it.hasNext()) {
ArchiveDirManagerInterface directoryManagerInterface = it.next();
directoryManagerInterface.removeLogFileListener(responseFactory);
}
QVCSEnterpriseServer.getConnectedUsersCollection().remove(responseFactory);
// Decrement the number of logged on users with the
// license manager.
if (responseFactory.getIsUserLoggedIn()) {
ServerTransactionManager.getInstance().flushClientTransaction(responseFactory);
LicenseManager.getInstance().logoutUser(responseFactory.getUserName(), responseFactory.getClientIPAddress());
}
}
} catch (IOException e) {
LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e));
}
}
}
}